merlin16_config.c (43318B)
1 /*********************************************************************************** 2 *********************************************************************************** 3 * File Name : merlin16_config.c * 4 * Created On : 03 Nov 2015 * 5 * Created By : Brent Roberts * 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_config.c 23 * Implementation of API config functions 24 */ 25 26 #include <phymod/phymod.h> 27 #include <phymod/phymod_system.h> 28 #include "merlin16_config.h" 29 #include "merlin16_access.h" 30 #include "merlin16_common.h" 31 #include "merlin16_functions.h" 32 #include "merlin16_internal.h" 33 #include "merlin16_internal_error.h" 34 #include "merlin16_select_defns.h" 35 #include "merlin16_enum.h" 36 #include "merlin16_dependencies.h" 37 38 /* If SERDES_EVAL is defined, then is_ate_log_enabled() is queried to *\ 39 \* know whether to log ATE. merlin16_access.h provides that function. */ 40 41 42 43 /*******************************/ 44 /* Stop/Resume RX Adaptation */ 45 /*******************************/ 46 47 err_code_t merlin16_stop_rx_adaptation(srds_access_t *sa__, uint8_t enable) { 48 49 if (enable) { 50 err_code_t err_code; 51 err_code = merlin16_pmd_uc_control(sa__, CMD_UC_CTRL_STOP_GRACEFULLY,GRACEFUL_STOP_TIME); 52 if(err_code) { 53 uint8_t temp=0; 54 USR_PRINTF(("Warning Graceful stop request returned error %d; Requesting a forceful stop\n",err_code)); 55 temp = merlin16_INTERNAL_stop_micro(sa__,0,&err_code); 56 /* return value from merlin16_INTERNAL_stop_micro - immediate stop is not required */ 57 /* void casting to avoid compiler warning. */ 58 (void)temp; 59 } 60 return(err_code); 61 } 62 else { 63 return(merlin16_pmd_uc_control(sa__, CMD_UC_CTRL_RESUME,50)); 64 } 65 } 66 67 err_code_t merlin16_request_stop_rx_adaptation(srds_access_t *sa__) { 68 69 return(merlin16_pmd_uc_control_return_immediate(sa__, CMD_UC_CTRL_STOP_GRACEFULLY)); 70 } 71 72 /**********************/ 73 /* uCode CRC Verify */ 74 /**********************/ 75 76 err_code_t merlin16_ucode_crc_verify(srds_access_t *sa__, uint16_t ucode_len,uint16_t expected_crc_value) { 77 uint16_t calc_crc; 78 EFUN(merlin16_pmd_uc_cmd_with_data(sa__, CMD_CALC_CRC,0,ucode_len,200)); 79 80 ESTM(calc_crc = rd_uc_dsc_data()); 81 if(calc_crc != expected_crc_value) { 82 EFUN_PRINTF(("Microcode CRC did not match expected=%04x : calculated=%04x\n",expected_crc_value, calc_crc)); 83 return(_error(ERR_CODE_UC_CRC_NOT_MATCH)); 84 } 85 return(ERR_CODE_NONE); 86 } 87 88 err_code_t merlin16_start_ucode_crc_calc(srds_access_t *sa__, uint16_t ucode_len) { 89 EFUN(merlin16_pmd_uc_cmd_with_data_return_immediate(sa__, CMD_CALC_CRC, 0, ucode_len)); /* Invoke Calculate CRC command and return control immediately */ 90 return(ERR_CODE_NONE); 91 } 92 93 err_code_t merlin16_check_ucode_crc(srds_access_t *sa__, uint16_t expected_crc_value, uint32_t timeout_ms) { 94 uint16_t calc_crc; 95 err_code_t err_code; 96 97 err_code = merlin16_INTERNAL_poll_uc_dsc_ready_for_cmd_equals_1(sa__, timeout_ms, CMD_CALC_CRC); /* Poll for uc_dsc_ready_for_cmd = 1 to indicate merlin16 ready for command */ 98 if (err_code) { 99 EFUN_PRINTF(("ERROR : DSC ready for command timed out. Previous uC command not finished yet\n")); 100 return (err_code); 101 } 102 ESTM(calc_crc = rd_uc_dsc_data()); 103 if(calc_crc != expected_crc_value) { 104 EFUN_PRINTF(("UC CRC did not match expected=%04x : calculated=%04x\n",expected_crc_value, calc_crc)); 105 return(_error(ERR_CODE_UC_CRC_NOT_MATCH)); 106 } 107 108 return(ERR_CODE_NONE); 109 } 110 111 112 /**************************************************************/ 113 /* APIs to Write Lane Config and User variables into uC RAM */ 114 /**************************************************************/ 115 116 err_code_t merlin16_set_uc_lane_cfg(srds_access_t *sa__, struct merlin16_uc_lane_config_st struct_val) { 117 uint8_t reset_state; 118 ESTM(reset_state = rd_rx_lane_dp_reset_state()); 119 if(reset_state < 7) { 120 EFUN_PRINTF(("ERROR: merlin16_set_uc_lane_cfg(..) called without ln_dp_s_rstb=0\n")); 121 return (_error(ERR_CODE_LANE_DP_NOT_RESET)); 122 } 123 EFUN(merlin16_INTERNAL_update_uc_lane_config_word(&struct_val)); 124 return(wrv_config_word(struct_val.word)); 125 } 126 127 /******************************************************************/ 128 /* APIs to Read Core/Lane Config and User variables from uC RAM */ 129 /******************************************************************/ 130 131 err_code_t merlin16_get_uc_core_config(srds_access_t *sa__, struct merlin16_uc_core_config_st *get_val) 132 { 133 134 if(!get_val) { 135 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 136 } 137 ESTM(get_val->word = rdcv_config_word()); 138 EFUN(merlin16_INTERNAL_update_uc_core_config_st(get_val)); 139 return ERR_CODE_NONE; 140 } 141 142 err_code_t merlin16_get_uc_lane_cfg(srds_access_t *sa__, struct merlin16_uc_lane_config_st *get_val) { 143 144 if(!get_val) { 145 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 146 } 147 ESTM(get_val->word = rdv_config_word()); 148 EFUN(merlin16_INTERNAL_update_uc_lane_config_st(get_val)); 149 return (ERR_CODE_NONE); 150 } 151 152 /*--------------------------------------------*/ 153 /* APIs to Enable or Disable datapath reset */ 154 /*--------------------------------------------*/ 155 156 err_code_t merlin16_tx_dp_reset(srds_access_t *sa__, uint8_t enable) { 157 if (enable) { 158 EFUN(wr_tx_ln_dp_s_rstb(0x0)); 159 } else { 160 EFUN(wr_tx_ln_dp_s_rstb(0x1)); 161 EFUN(wr_tx_uc_ack_lane_dp_reset(0x1)); 162 EFUN(wr_tx_uc_ack_lane_cfg_done(0x1)); 163 } 164 return ERR_CODE_NONE; 165 } 166 167 err_code_t merlin16_rx_dp_reset(srds_access_t *sa__, uint8_t enable) { 168 if (enable) { 169 EFUN(wr_rx_ln_dp_s_rstb(0x0)); 170 } else { 171 EFUN(wr_rx_ln_dp_s_rstb(0x1)); 172 } 173 return ERR_CODE_NONE; 174 } 175 176 err_code_t merlin16_core_dp_reset(srds_access_t *sa__, uint8_t enable){ 177 if (enable) { 178 EFUN(wrc_core_dp_s_rstb(0x0)); 179 } else { 180 EFUN(wrc_core_dp_s_rstb(0x1)); 181 } 182 return ERR_CODE_NONE; 183 } 184 185 /********************************/ 186 /* Loading ucode through PRAM */ 187 /********************************/ 188 err_code_t merlin16_ucode_pram_load(srds_access_t *sa__, char const * ucode_image, uint32_t ucode_len) { 189 uint16_t ucode_len_remainder = ((ucode_len + 3) & 0xFFFFFFFC) - ucode_len; 190 191 if(!ucode_image) { 192 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 193 } 194 195 if (ucode_len > UCODE_MAX_SIZE) { /* uCode size should be less than UCODE_MAX_SIZE */ 196 return (_error(ERR_CODE_INVALID_UCODE_LEN)); 197 } 198 199 EFUN(wrc_micro_master_clk_en(0x1)); /* Enable clock to microcontroller subsystem */ 200 EFUN(wrc_micro_master_rstb(0x1)); /* De-assert reset to microcontroller sybsystem */ 201 EFUN(wrc_micro_master_rstb(0x0)); /* Assert reset to microcontroller sybsystem - Toggling reset*/ 202 EFUN(wrc_micro_master_rstb(0x1)); /* De-assert reset to microcontroller sybsystem */ 203 204 EFUN(wrc_micro_ra_init(0x1)); /* Set initialization command to initialize code RAM */ 205 EFUN(merlin16_INTERNAL_poll_micro_ra_initdone(sa__, 250));/* Poll for micro_ra_initdone = 1 to indicate initialization done */ 206 207 EFUN(wrc_micro_ra_init(0x2)); /* Write command for data RAM initialization */ 208 EFUN(merlin16_INTERNAL_poll_micro_ra_initdone(sa__, 250)); /* Poll status of data RAM initialization */ 209 210 EFUN(wrc_micro_ra_init(0x0)); /* Clear initialization command */ 211 212 213 EFUN(wrc_micro_pramif_ahb_wraddr_msw(0x0000)); 214 EFUN(wrc_micro_pramif_ahb_wraddr_lsw(0x0000)); 215 EFUN(wrc_micro_pram_if_rstb(1)); 216 EFUN(wrc_micro_pramif_en(1)); 217 218 /* Wait 8 pram clocks */ 219 EFUN(USR_DELAY_US(1)); 220 221 /* write ucode into pram */ 222 while (ucode_len > 0) { 223 EFUN(merlin16_pmd_wr_pram(sa__, *ucode_image)); 224 --ucode_len; 225 ++ucode_image; 226 } 227 228 /* Pad to 32 bits */ 229 while (ucode_len_remainder > 0) { 230 EFUN(merlin16_pmd_wr_pram(sa__, 0)); 231 --ucode_len_remainder; 232 } 233 234 /* Wait 8 pram clocks */ 235 EFUN(USR_DELAY_US(1)); 236 237 238 EFUN(wrc_micro_pramif_en(0)); 239 EFUN(wrc_micro_core_clk_en(1)); 240 /* EFUN(wrc_micro_core_rstb(1)); */ 241 return(ERR_CODE_NONE); 242 } 243 244 /************************************/ 245 /* Accessing core_config_from_pcs */ 246 /************************************/ 247 248 err_code_t merlin16_set_core_config_from_pcs(srds_access_t *sa__, uint8_t core_cfg_from_pcs) { 249 struct merlin16_uc_core_config_st core_config; 250 EFUN(merlin16_get_uc_core_config(sa__, &core_config)); 251 core_config.field.core_cfg_from_pcs = core_cfg_from_pcs; 252 EFUN(merlin16_INTERNAL_set_uc_core_config(sa__, core_config)); 253 return (ERR_CODE_NONE); 254 } 255 256 #if defined(MERLIN_SHORTFIN) || defined(FALCON_SHORTFIN) 257 err_code_t merlin16_set_an_los_workaround(srds_access_t *sa__, uint8_t an_los_workaround) { 258 struct merlin16_uc_core_config_st core_config; 259 EFUN(merlin16_get_uc_core_config(sa__, &core_config)); 260 core_config.field.an_los_workaround = an_los_workaround; 261 EFUN(merlin16_INTERNAL_set_uc_core_config(sa__, core_config)); 262 return (ERR_CODE_NONE); 263 } 264 #endif 265 266 /******************/ 267 /* Lane Mapping */ 268 /******************/ 269 270 err_code_t merlin16_map_lanes(srds_access_t *sa__, uint8_t num_lanes, uint8_t const *tx_lane_map, uint8_t const *rx_lane_map) { 271 uint8_t rd_val = 0; 272 273 /* Verify that the core data path is held in reset. */ 274 ESTM(rd_val = rdc_core_dp_s_rstb()); 275 if (rd_val != 0) { 276 EFUN_PRINTF(("ERROR: core data path reset is not de-asserted\n")); 277 return (ERR_CODE_UC_NOT_RESET); 278 } 279 280 /* Verify that all micros are held in reset. */ 281 282 ESTM(rd_val = rdc_micro_core_rstb()); 283 if (rd_val != 0) { 284 return (ERR_CODE_UC_NOT_RESET); 285 } 286 287 /* Verify that the num_lanes parameter is correct. */ 288 ESTM(rd_val = rdc_revid_multiplicity()); 289 if (rd_val != num_lanes) { 290 return (ERR_CODE_BAD_LANE_COUNT); 291 } 292 293 /* Verify that tx_lane_map and rx_lane_map are valid. */ 294 { 295 uint8_t index1, index2; 296 /*uint8_t lp_message_printed = 0;*/ 297 for (index1=0; index1<num_lanes; ++index1) { 298 299 /* Verify that a lane map is not to an invalid lane. */ 300 if ((tx_lane_map[index1] >= num_lanes) 301 || (rx_lane_map[index1] >= num_lanes)){ 302 return (ERR_CODE_BAD_LANE); 303 } 304 #if 0 305 /* Warn if an RX lane mapping is not the same as TX. */ 306 if ((tx_lane_map[index1] != rx_lane_map[index1]) 307 && !lp_message_printed) { 308 ESTM_PRINTF(("Warning: In core %d, TX lane %d is mapped to %d, while RX lane %d is mapped to %d.\n Digital and remote loopback will not operate as expected.\n Further warnings are suppressed.\n", merlin16_get_core(sa__), index1, tx_lane_map[index1], index1, rx_lane_map[index1])); 309 lp_message_printed = 1; 310 } 311 #endif 312 313 /* Verify that a lane map is not used twice. */ 314 for (index2=index1+1; index2<num_lanes; ++index2) { 315 if ((tx_lane_map[index1] == tx_lane_map[index2]) 316 || (rx_lane_map[index1] == rx_lane_map[index2])) { 317 return (ERR_CODE_BAD_LANE); 318 } 319 } 320 } 321 } 322 323 /* Write the map bitfields. 324 * Support up to 8 lanes. 325 */ 326 EFUN(wrc_tx_lane_addr_0(*(tx_lane_map++))); EFUN(wrc_rx_lane_addr_0(*(rx_lane_map++))); 327 #if defined(wrc_tx_lane_addr_1) 328 if (num_lanes > 1) { EFUN(wrc_tx_lane_addr_1(*(tx_lane_map++))); EFUN(wrc_rx_lane_addr_1(*(rx_lane_map++))); } 329 #if defined(wrc_tx_lane_addr_2) 330 if (num_lanes > 2) { EFUN(wrc_tx_lane_addr_2(*(tx_lane_map++))); EFUN(wrc_rx_lane_addr_2(*(rx_lane_map++))); } 331 #if defined(wrc_tx_lane_addr_3) 332 if (num_lanes > 3) { EFUN(wrc_tx_lane_addr_3(*(tx_lane_map++))); EFUN(wrc_rx_lane_addr_3(*(rx_lane_map++))); } 333 #if defined(wrc_tx_lane_addr_4) 334 if (num_lanes > 4) { EFUN(wrc_tx_lane_addr_4(*(tx_lane_map++))); EFUN(wrc_rx_lane_addr_4(*(rx_lane_map++))); } 335 #if defined(wrc_tx_lane_addr_5) 336 if (num_lanes > 5) { EFUN(wrc_tx_lane_addr_5(*(tx_lane_map++))); EFUN(wrc_rx_lane_addr_5(*(rx_lane_map++))); } 337 #if defined(wrc_tx_lane_addr_6) 338 if (num_lanes > 6) { EFUN(wrc_tx_lane_addr_6(*(tx_lane_map++))); EFUN(wrc_rx_lane_addr_6(*(rx_lane_map++))); } 339 #if defined(wrc_tx_lane_addr_7) 340 if (num_lanes > 7) { EFUN(wrc_tx_lane_addr_7(*(tx_lane_map++))); EFUN(wrc_rx_lane_addr_7(*(rx_lane_map++))); } 341 #endif 342 #endif 343 #endif 344 #endif 345 #endif 346 #endif 347 #endif 348 return (ERR_CODE_NONE); 349 } 350 351 /************************/ 352 /* Serdes API Version */ 353 /************************/ 354 355 err_code_t merlin16_version(uint32_t *api_version) { 356 357 if(!api_version) { 358 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 359 } 360 *api_version = 0xA10710; 361 return (ERR_CODE_NONE); 362 } 363 364 /*****************/ 365 /* PMD_RX_LOCK */ 366 /*****************/ 367 368 err_code_t merlin16_pmd_lock_status(srds_access_t *sa__, uint8_t *pmd_rx_lock) { 369 if(!pmd_rx_lock) { 370 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 371 } 372 ESTM(*pmd_rx_lock = rd_pmd_rx_lock()); 373 return (ERR_CODE_NONE); 374 } 375 376 /**********************************/ 377 /* Serdes TX disable/RX Restart */ 378 /**********************************/ 379 380 err_code_t merlin16_tx_disable(srds_access_t *sa__, uint8_t enable) { 381 382 if (enable) { 383 EFUN(wr_sdk_tx_disable(0x1)); 384 } 385 else { 386 EFUN(wr_sdk_tx_disable(0x0)); 387 } 388 return(ERR_CODE_NONE); 389 } 390 391 err_code_t merlin16_rx_restart(srds_access_t *sa__, uint8_t enable) { 392 393 EFUN(wr_rx_restart_pmd_hold(enable)); 394 return(ERR_CODE_NONE); 395 } 396 /******************************************************/ 397 /* Single function to set/get all RX AFE parameters */ 398 /******************************************************/ 399 400 err_code_t merlin16_write_rx_afe(srds_access_t *sa__, enum srds_rx_afe_settings_enum param, int8_t val) { 401 /* Assumes the micro is not actively tuning */ 402 403 switch(param) { 404 case RX_AFE_PF: 405 return(merlin16_INTERNAL_set_rx_pf_main(sa__, val)); 406 407 case RX_AFE_PF2: 408 return(merlin16_INTERNAL_set_rx_pf2(sa__, val)); 409 410 case RX_AFE_VGA: 411 return(merlin16_INTERNAL_set_rx_vga(sa__, val)); 412 413 case RX_AFE_DFE1: 414 return(merlin16_INTERNAL_set_rx_dfe1(sa__, val)); 415 416 case RX_AFE_DFE2: 417 return(merlin16_INTERNAL_set_rx_dfe2(sa__, val)); 418 419 case RX_AFE_DFE3: 420 return(merlin16_INTERNAL_set_rx_dfe3(sa__, val)); 421 422 case RX_AFE_DFE4: 423 return(merlin16_INTERNAL_set_rx_dfe4(sa__, val)); 424 425 case RX_AFE_DFE5: 426 return(merlin16_INTERNAL_set_rx_dfe5(sa__, val)); 427 428 default: 429 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 430 } 431 } 432 433 err_code_t merlin16_read_rx_afe(srds_access_t *sa__, enum srds_rx_afe_settings_enum param, int8_t *val) { 434 /* Assumes the micro is not actively tuning */ 435 if(!val) { 436 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 437 } 438 439 switch(param) { 440 case RX_AFE_PF: 441 EFUN(merlin16_INTERNAL_get_rx_pf_main(sa__, val)); 442 break; 443 case RX_AFE_PF2: 444 EFUN(merlin16_INTERNAL_get_rx_pf2(sa__, val)); 445 break; 446 case RX_AFE_VGA: 447 EFUN(merlin16_INTERNAL_get_rx_vga(sa__, val)); 448 break; 449 450 case RX_AFE_DFE1: 451 EFUN(merlin16_INTERNAL_get_rx_dfe1(sa__, val)); 452 break; 453 case RX_AFE_DFE2: 454 EFUN(merlin16_INTERNAL_get_rx_dfe2(sa__, val)); 455 break; 456 case RX_AFE_DFE3: 457 EFUN(merlin16_INTERNAL_get_rx_dfe3(sa__, val)); 458 break; 459 case RX_AFE_DFE4: 460 EFUN(merlin16_INTERNAL_get_rx_dfe4(sa__, val)); 461 break; 462 case RX_AFE_DFE5: 463 EFUN(merlin16_INTERNAL_get_rx_dfe5(sa__, val)); 464 break; 465 default: 466 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 467 } 468 469 return(ERR_CODE_NONE); 470 } 471 472 473 /**********************************************/ 474 /* Loopback and Ultra-Low Latency Functions */ 475 /**********************************************/ 476 477 /* Locks TX_PI to Loop timing */ 478 err_code_t merlin16_loop_timing(srds_access_t *sa__, uint8_t enable) { 479 480 if (enable) { 481 EFUN(wr_tx_pi_repeater_mode_en(0x0)); 482 EFUN(wr_tx_pi_en(0x1)); /* TX_PI enable: 0 = diabled, 1 = enabled */ 483 EFUN(wr_tx_pi_jitter_filter_en(0x1)); /* Jitter filter enable to lock freq: 0 = diabled, 1 = enabled */ 484 EFUN(USR_DELAY_US(25)); /* Wait for tclk to lock to CDR */ 485 } 486 else { 487 EFUN(wr_tx_pi_jitter_filter_en(0x0)); /* Jitter filter enable to lock freq: 0 = diabled, 1 = enabled */ 488 EFUN(wr_tx_pi_en(0x0)); /* TX_PI enable: 0 = diabled, 1 = enabled */ 489 EFUN(wr_tx_pi_repeater_mode_en(0x1)); 490 } 491 return (ERR_CODE_NONE); 492 } 493 494 /* Setup Remote Loopback mode */ 495 err_code_t merlin16_rmt_lpbk(srds_access_t *sa__, uint8_t enable) { 496 if (enable) { 497 EFUN(merlin16_loop_timing(sa__, enable)); 498 EFUN(wr_tx_pi_ext_ctrl_en(0x1)); /* PD path enable: 0 = diabled, 1 = enabled */ 499 EFUN(wr_rmt_lpbk_en(0x1)); /* Remote Loopback Enable: 0 = diabled, 1 = enable */ 500 EFUN(USR_DELAY_US(50)); /* Wait for rclk and tclk phase lock before expecing good data from rmt loopback */ 501 } else { /* Might require longer wait time for smaller values of tx_pi_ext_phase_bwsel_integ */ 502 EFUN(wr_rmt_lpbk_en(0x0)); /* Remote Loopback Enable: 0 = diabled, 1 = enable */ 503 EFUN(wr_tx_pi_ext_ctrl_en(0x0)); /* PD path enable: 0 = diabled, 1 = enabled */ 504 EFUN(merlin16_loop_timing(sa__, enable)); 505 } 506 return (ERR_CODE_NONE); 507 } 508 509 /* Repeater Only APIs (Not applicable to PMD) */ 510 511 512 513 /* TX PI setup for Repeater Mode */ 514 err_code_t merlin16_tx_rptr_mode_timing(srds_access_t *sa__, uint8_t enable) { 515 /* Enable TX PI and turn on 1st order loop in jitter filter */ 516 EFUN(wr_tx_pi_repeater_mode_en(0x1)); 517 EFUN(wr_tx_pi_en(enable)); /* TX_PI enable: 0 = diabled, 1 = enabled */ 518 EFUN(wr_tx_pi_jitter_filter_en(enable)); /* Jitter filter enable to lock freq: 0 = diabled, 1 = enabled */ 519 EFUN(USR_DELAY_US(25)); /* Wait for TX_PI to settle */ 520 return (ERR_CODE_NONE); 521 } 522 523 /* RX setup for Repeater Mode timing */ 524 err_code_t merlin16_rx_rptr_mode_timing(srds_access_t *sa__, uint8_t enable) { 525 (void)enable; 526 527 return (ERR_CODE_NONE); 528 } 529 530 /* Switch to remote loopback from NL mode in repeater */ 531 err_code_t merlin16_rmt_lpbk_from_nl(srds_access_t *sa__) { 532 EFUN(merlin16_rmt_lpbk(sa__, 0)); /* Reset TX_PI */ 533 EFUN(merlin16_rmt_lpbk(sa__, 1)); /* Enable RMT LPBK */ 534 return (ERR_CODE_NONE); 535 } 536 537 538 /* Switch back from remote loopback to NL mode in repeater */ 539 err_code_t merlin16_nl_from_rmt_lpbk(srds_access_t *sa__, enum srds_rptr_mode_enum mode) { 540 switch(mode) { 541 case DATA_IN_SIDE: 542 EFUN(merlin16_rx_rptr_mode_timing(sa__, 1)); /* Enable RX PI transfer */ 543 break; 544 case RMT_LPBK_SIDE: 545 EFUN(merlin16_rmt_lpbk(sa__, 0)); /* Reset TX_PI */ 546 EFUN(merlin16_tx_rptr_mode_timing(sa__, 1)); /* Enable jitter filter enable */ 547 EFUN(wr_ams_tx_ll_selpath_tx(0x0)); /* Select TX PCS data from PCS interface */ 548 break; 549 default : return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 550 } 551 return (ERR_CODE_NONE); 552 } 553 554 /********************************/ 555 /* TX_PI Fixed Frequency Mode */ 556 /********************************/ 557 /* TX_PI Frequency Override (Fixed Frequency Mode) */ 558 err_code_t merlin16_tx_pi_freq_override(srds_access_t *sa__, uint8_t enable, int16_t freq_override_val) { 559 if (enable) { 560 EFUN(wr_tx_pi_en(0x1)); /* TX_PI enable : 0 = disabled, 1 = enabled */ 561 EFUN(wr_tx_pi_freq_override_en(0x1)); /* Fixed freq mode enable: 0 = disabled, 1 = enabled */ 562 EFUN(wr_tx_pi_freq_override_val(freq_override_val)); /* Fixed Freq Override Value (+/-8192) */ 563 } 564 else { 565 EFUN(wr_tx_pi_freq_override_val(0)); /* Fixed Freq Override Value to 0 */ 566 EFUN(wr_tx_pi_freq_override_en(0x0)); /* Fixed freq mode enable: 0 = disabled, 1 = enabled */ 567 EFUN(wr_tx_pi_en(0x0)); /* TX_PI enable : 0 = disabled, 1 = enabled */ 568 } 569 return (ERR_CODE_NONE); 570 } 571 572 /*********************************/ 573 /* uc_active and uc_reset APIs */ 574 /*********************************/ 575 576 /* Enable or Disable the uC reset */ 577 err_code_t merlin16_uc_reset(srds_access_t *sa__, uint8_t enable) { 578 ucode_info_t ucode_info = {0}; 579 return merlin16_uc_reset_with_info(sa__, enable, ucode_info); 580 } 581 582 err_code_t merlin16_uc_reset_with_info(srds_access_t *sa__, uint8_t enable, ucode_info_t ucode_info) { 583 if (enable) { 584 /* Assert micro reset and reset all micro registers (all non-status registers written to default value) */ 585 EFUN(wrc_micro_core_clk_en(0x0)); /* Disable clock to M0 core */ 586 587 EFUN(wrc_micro_master_clk_en(0x0)); /* Disable clock to microcontroller subsystem */ 588 EFUN(merlin16_pmd_wr_reg(sa__, 0xD200, 0x0000)); 589 EFUN(merlin16_pmd_wr_reg(sa__, 0xD201, 0x0000)); 590 EFUN(merlin16_pmd_wr_reg(sa__, 0xD202, 0x0000)); 591 EFUN(merlin16_pmd_wr_reg(sa__, 0xD204, 0x0000)); 592 EFUN(merlin16_pmd_wr_reg(sa__, 0xD205, 0x0000)); 593 EFUN(merlin16_pmd_wr_reg(sa__, 0xD206, 0x0000)); 594 EFUN(merlin16_pmd_wr_reg(sa__, 0xD207, 0x0000)); 595 EFUN(merlin16_pmd_wr_reg(sa__, 0xD208, 0x0000)); 596 EFUN(merlin16_pmd_wr_reg(sa__, 0xD209, 0x0000)); 597 EFUN(merlin16_pmd_wr_reg(sa__, 0xD20A, 0x0000)); 598 EFUN(merlin16_pmd_wr_reg(sa__, 0xD20B, 0x0000)); 599 EFUN(merlin16_pmd_wr_reg(sa__, 0xD20C, 0x0000)); 600 EFUN(merlin16_pmd_wr_reg(sa__, 0xD20D, 0x0000)); 601 EFUN(merlin16_pmd_wr_reg(sa__, 0xD20E, 0x0000)); 602 EFUN(merlin16_pmd_wr_reg(sa__, 0xD211, 0x0000)); 603 EFUN(merlin16_pmd_wr_reg(sa__, 0xD212, 0x0000)); 604 EFUN(merlin16_pmd_wr_reg(sa__, 0xD213, 0x0000)); 605 EFUN(merlin16_pmd_wr_reg(sa__, 0xD214, 0x0000)); 606 EFUN(merlin16_pmd_wr_reg(sa__, 0xD215, 0x0000)); 607 EFUN(merlin16_pmd_wr_reg(sa__, 0xD216, 0x0007)); 608 EFUN(merlin16_pmd_wr_reg(sa__, 0xD217, 0x0000)); 609 EFUN(merlin16_pmd_wr_reg(sa__, 0xD218, 0x0000)); 610 EFUN(merlin16_pmd_wr_reg(sa__, 0xD219, 0x0000)); 611 EFUN(merlin16_pmd_wr_reg(sa__, 0xD21A, 0x0000)); 612 EFUN(merlin16_pmd_wr_reg(sa__, 0xD21B, 0x0000)); 613 EFUN(merlin16_pmd_wr_reg(sa__, 0xD220, 0x0000)); 614 EFUN(merlin16_pmd_wr_reg(sa__, 0xD221, 0x0000)); 615 EFUN(merlin16_pmd_wr_reg(sa__, 0xD224, 0x0000)); 616 617 EFUN(merlin16_pmd_wr_reg(sa__, 0xD225, 0x8301)); 618 619 EFUN(merlin16_pmd_wr_reg(sa__, 0xD226, 0x0000)); 620 EFUN(merlin16_pmd_wr_reg(sa__, 0xD228, 0x0101)); 621 EFUN(merlin16_pmd_wr_reg(sa__, 0xD229, 0x0000)); 622 EFUN(merlin16_pmd_wr_reg(sa__, 0xD22A, 0x0000)); 623 } 624 else { 625 /* De-assert micro reset - Start executing code */ 626 EFUN(wrc_micro_master_clk_en (0x1)); /* Enable clock to microcontroller subsystem */ 627 EFUN(wrc_micro_master_rstb (0x1)); /* De-assert reset to microcontroller sybsystem */ 628 629 EFUN(wrc_micro_core_clk_en (0x1)); /* Enable clock to M0 core */ 630 EFUN(wrc_micro_core_rstb (0x1)); 631 } 632 return (ERR_CODE_NONE); 633 } 634 635 /* Wait for uC to become active */ 636 err_code_t merlin16_wait_uc_active(srds_access_t *sa__) { 637 uint16_t loop; 638 for (loop = 0; loop < 10000; loop++) { 639 uint16_t rddata; 640 ESTM(rddata = rdc_uc_active()); 641 if (rddata) { 642 return (ERR_CODE_NONE); 643 } 644 if (loop>10) { 645 EFUN(USR_DELAY_US(1)); 646 } 647 } 648 return (_error(ERR_CODE_MICRO_INIT_NOT_DONE)); 649 } 650 651 static err_code_t merlin16_init_merlin16_info_fill(srds_access_t *sa__, merlin16_info_t * const merlin16_info_ptr) { 652 653 uint32_t info_table[INFO_TABLE_END / sizeof(uint32_t)]; 654 uint32_t info_table_signature; 655 uint8_t info_table_version; 656 err_code_t err_code = ERR_CODE_NONE; 657 658 if (merlin16_info_ptr == 0) { 659 EFUN_PRINTF(("ERROR: Info table pointer is null.\n")); 660 return (_error(ERR_CODE_INFO_TABLE_ERROR)); 661 } 662 663 /* runtime optimization: If table was already filled - no point in filling it again */ 664 if (merlin16_info_ptr->valid) { 665 return (ERR_CODE_NONE); 666 } 667 668 if (merlin16_info_ptr->signature == SRDS_INFO_SIGNATURE) { 669 /*Already initalized and so check for microcode version and exit with proper status*/ 670 err_code = merlin16_INTERNAL_match_ucode_from_info(sa__); 671 672 if (err_code == ERR_CODE_NONE) { 673 /* ucode version match */ 674 return (ERR_CODE_NONE); 675 } else { 676 /* ucode version mismatch */ 677 return (_error(ERR_CODE_MICRO_INIT_NOT_DONE)); 678 } 679 } 680 /*Never initialized so far, continue with initialization */ 681 682 err_code = merlin16_rdblk_uc_prog_ram(sa__, (uint8_t *)info_table, INFO_TABLE_RAM_BASE, INFO_TABLE_END); 683 /* Release lock before returning from the call to avoid deadlock */ 684 if (ERR_CODE_NONE != err_code) { 685 return (_error(err_code)); 686 } 687 688 info_table_signature = info_table[INFO_TABLE_OFFS_SIGNATURE / sizeof(uint32_t)]; 689 info_table_version = (uint8_t)(info_table_signature >> 24); 690 if (((info_table_signature & 0x00FFFFFF) != 0x666E49) 691 || (!( ((info_table_version >= 0x32) && (info_table_version <= 0x39)) 692 || ((info_table_version >= 0x41) && (info_table_version <= 0x5A))))) { 693 return (_error(ERR_CODE_INFO_TABLE_ERROR)); 694 } 695 696 merlin16_info_ptr->lane_count = info_table[INFO_TABLE_OFFS_OTHER_SIZE / sizeof(uint32_t)] & 0xFF; 697 merlin16_info_ptr->trace_memory_descending_writes = ((info_table[INFO_TABLE_OFFS_OTHER_SIZE / sizeof(uint32_t)] & 0x1000000) != 0); 698 699 merlin16_info_ptr->core_var_ram_size = (info_table[INFO_TABLE_OFFS_OTHER_SIZE / sizeof(uint32_t)] >> 8) & 0xFF; 700 701 merlin16_info_ptr->lane_var_ram_size = (info_table[INFO_TABLE_OFFS_TRACE_LANE_MEM_SIZE / sizeof(uint32_t)] >> 16) & 0xFFFF; 702 703 merlin16_info_ptr->diag_mem_ram_size = (info_table[INFO_TABLE_OFFS_TRACE_LANE_MEM_SIZE / sizeof(uint32_t)] & 0xFFFF) / merlin16_info_ptr->lane_count; 704 merlin16_info_ptr->trace_mem_ram_size = (info_table[INFO_TABLE_OFFS_TRACE_LANE_MEM_SIZE / sizeof(uint32_t)] & 0xFFFF); 705 706 merlin16_info_ptr->diag_mem_ram_base = info_table[INFO_TABLE_OFFS_TRACE_MEM_PTR / sizeof(uint32_t)]; 707 merlin16_info_ptr->trace_mem_ram_base = merlin16_info_ptr->diag_mem_ram_base; 708 709 merlin16_info_ptr->core_var_ram_base = info_table[INFO_TABLE_OFFS_CORE_MEM_PTR / sizeof(uint32_t)]; 710 711 merlin16_info_ptr->micro_var_ram_base = info_table[INFO_TABLE_OFFS_MICRO_MEM_PTR / sizeof(uint32_t)]; 712 merlin16_info_ptr->micro_var_ram_size = (info_table[INFO_TABLE_OFFS_OTHER_SIZE_2 / sizeof(uint32_t)] >> 4) & 0xFF; 713 714 merlin16_info_ptr->lane_var_ram_base = info_table[INFO_TABLE_OFFS_LANE_MEM_PTR / sizeof(uint32_t)]; 715 716 717 718 if (info_table_version < 0x34) { 719 merlin16_info_ptr->micro_count = 1; 720 } else { 721 merlin16_info_ptr->micro_count = info_table[INFO_TABLE_OFFS_OTHER_SIZE_2 / sizeof(uint32_t)] & 0xF; 722 } 723 724 if (info_table_version < 0x36) { 725 merlin16_info_ptr->grp_ram_size = 0; 726 } else { 727 merlin16_info_ptr->grp_ram_size = info_table[INFO_TABLE_OFFS_GROUP_RAM_SIZE / sizeof(uint32_t)] & 0xFFFF; 728 } 729 merlin16_info_ptr->ucode_version = info_table[INFO_TABLE_OFFS_UC_VERSION /sizeof(uint32_t)]; 730 merlin16_info_ptr->signature = SRDS_INFO_SIGNATURE; 731 merlin16_info_ptr->valid = 1; 732 733 return (ERR_CODE_NONE); 734 } 735 736 err_code_t merlin16_init_merlin16_info (srds_access_t *sa__) { 737 int level, rv; 738 merlin16_info_t * const merlin16_info_ptr = merlin16_INTERNAL_get_merlin16_info_ptr(); 739 740 level = PHYMOD_SPLHI(); /* to protect critical code when filling the global falcon16_tsc_inf table */ 741 rv = merlin16_init_merlin16_info_fill(sa__, merlin16_info_ptr); 742 PHYMOD_SPL(level); /* end of critical code */ 743 EFUN(rv); /* error checking is after completing the critical code, to avoid stuck with the high priority task */ 744 745 return (ERR_CODE_NONE); 746 747 } 748 /*-----------------*/ 749 /* Configure PLL */ 750 /*-----------------*/ 751 752 err_code_t merlin16_configure_pll_refclk_div(srds_access_t *sa__, 753 enum merlin16_pll_refclk_enum refclk, 754 enum merlin16_pll_div_enum div) { 755 return merlin16_INTERNAL_configure_pll(sa__, refclk, div, 0, MERLIN16_PLL_OPTION_NONE); 756 } 757 758 err_code_t merlin16_configure_pll_refclk_vco(srds_access_t *sa__, 759 enum merlin16_pll_refclk_enum refclk, 760 uint32_t vco_freq_khz) { 761 return merlin16_INTERNAL_configure_pll(sa__, refclk, MERLIN16_PLL_DIV_UNKNOWN, vco_freq_khz, MERLIN16_PLL_OPTION_NONE); 762 } 763 764 err_code_t merlin16_configure_pll_div_vco(srds_access_t *sa__, 765 enum merlin16_pll_div_enum div, 766 uint32_t vco_freq_khz) { 767 return merlin16_INTERNAL_configure_pll(sa__, MERLIN16_PLL_REFCLK_UNKNOWN, div, vco_freq_khz, MERLIN16_PLL_OPTION_NONE); 768 } 769 770 /* following routines divide refclk input by 2 to prevent fracn mode */ 771 err_code_t merlin16_configure_pll_refclk_div_div2refclk(srds_access_t *sa__, 772 enum merlin16_pll_refclk_enum refclk, 773 enum merlin16_pll_div_enum div) { 774 return merlin16_INTERNAL_configure_pll(sa__, refclk, div, 0, MERLIN16_PLL_OPTION_REFCLK_DIV2_EN); 775 } 776 777 err_code_t merlin16_configure_pll_refclk_vco_div2refclk(srds_access_t *sa__, 778 enum merlin16_pll_refclk_enum refclk, 779 uint32_t vco_freq_khz) { 780 return merlin16_INTERNAL_configure_pll(sa__, refclk, MERLIN16_PLL_DIV_UNKNOWN, vco_freq_khz, MERLIN16_PLL_OPTION_REFCLK_DIV2_EN); 781 } 782 783 err_code_t merlin16_configure_pll_div_vco_div2refclk(srds_access_t *sa__, 784 enum merlin16_pll_div_enum div, 785 uint32_t vco_freq_khz) { 786 return merlin16_INTERNAL_configure_pll(sa__, MERLIN16_PLL_REFCLK_UNKNOWN, div, vco_freq_khz, MERLIN16_PLL_OPTION_REFCLK_DIV2_EN); 787 } 788 /* following routines divide refclk input by 2 to prevent fracn mode */ 789 err_code_t merlin16_configure_pll_refclk_div_div4refclk(srds_access_t *sa__, 790 enum merlin16_pll_refclk_enum refclk, 791 enum merlin16_pll_div_enum div) { 792 return merlin16_INTERNAL_configure_pll(sa__, refclk, div, 0, MERLIN16_PLL_OPTION_REFCLK_DIV4_EN); 793 } 794 795 err_code_t merlin16_configure_pll_refclk_vco_div4refclk(srds_access_t *sa__, 796 enum merlin16_pll_refclk_enum refclk, 797 uint32_t vco_freq_khz) { 798 return merlin16_INTERNAL_configure_pll(sa__, refclk, MERLIN16_PLL_DIV_UNKNOWN, vco_freq_khz, MERLIN16_PLL_OPTION_REFCLK_DIV4_EN); 799 } 800 801 err_code_t merlin16_configure_pll_div_vco_div4refclk(srds_access_t *sa__, 802 enum merlin16_pll_div_enum div, 803 uint32_t vco_freq_khz) { 804 return merlin16_INTERNAL_configure_pll(sa__, MERLIN16_PLL_REFCLK_UNKNOWN, div, vco_freq_khz, MERLIN16_PLL_OPTION_REFCLK_DIV4_EN); 805 } 806 807 808 err_code_t merlin16_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) { 809 EFUN(merlin16_INTERNAL_get_vco_from_refclk_div(refclk_freq_hz, div, vco_freq_khz, pll_option)); 810 return (ERR_CODE_NONE); 811 } 812 813 814 /***********************************************/ 815 /* Microcode Load into Program RAM Functions */ 816 /***********************************************/ 817 818 /* uCode Load through Register (MDIO) Interface [Return Val = Error_Code (0 = PASS)] */ 819 err_code_t merlin16_ucode_mdio_load(srds_access_t *sa__, uint8_t *ucode_image, uint32_t ucode_len) { 820 uint32_t ucode_len_padded, count = 0; 821 uint16_t wrdata_lsw; 822 uint8_t wrdata_lsb; 823 824 if(!ucode_image) { 825 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 826 } 827 828 if (ucode_len > UCODE_MAX_SIZE) { /* uCode size should be less than UCODE_MAX_SIZE */ 829 return (_error(ERR_CODE_INVALID_UCODE_LEN)); 830 } 831 832 EFUN(wrc_micro_master_clk_en(0x1)); /* Enable clock to microcontroller subsystem */ 833 EFUN(wrc_micro_master_rstb(0x1)); /* De-assert reset to microcontroller sybsystem */ 834 EFUN(wrc_micro_master_rstb(0x0)); /* Assert reset to microcontroller sybsystem - Toggling reset*/ 835 EFUN(wrc_micro_master_rstb(0x1)); /* De-assert reset to microcontroller sybsystem */ 836 837 EFUN(wrc_micro_ra_init(0x1)); /* Set initialization command to initialize code RAM */ 838 EFUN(merlin16_INTERNAL_poll_micro_ra_initdone(sa__, 250)); /* Poll for micro_ra_initdone = 1 to indicate initialization done */ 839 840 EFUN(wrc_micro_ra_init(0x2)); /* Write command for data RAM initialization */ 841 EFUN(merlin16_INTERNAL_poll_micro_ra_initdone(sa__, 250)); /* Poll status of data RAM initialization */ 842 843 EFUN(wrc_micro_ra_init(0x0)); /* Clear initialization command */ 844 845 ucode_len_padded = ((ucode_len + 3) & 0xFFFFFFFC); /* Aligning ucode size to 4-byte boundary */ 846 847 /* Code to Load microcode */ 848 EFUN(wrc_micro_autoinc_wraddr_en(0x1)); /* To auto increment RAM write address */ 849 EFUN(wrc_micro_ra_wrdatasize(0x1)); /* Select 16bit transfers */ 850 EFUN(wrc_micro_ra_wraddr_msw(0x0)); /* Upper 16bits of start address of Program RAM where the ucode is to be loaded */ 851 EFUN(wrc_micro_ra_wraddr_lsw(0x0)); /* Lower 16bits of start address of Program RAM where the ucode is to be loaded */ 852 853 do { /* ucode_image loaded 16bits at a time */ 854 wrdata_lsb = (count < ucode_len) ? ucode_image[count] : 0x0; /* wrdata_lsb read from ucode_image; zero padded to 4byte boundary */ 855 count++; 856 wrdata_lsw = (count < ucode_len) ? ucode_image[count] : 0x0; /* wrdata_msb read from ucode_image; zero padded to 4byte boundary */ 857 count++; 858 wrdata_lsw = ((wrdata_lsw << 8) | wrdata_lsb); /* 16bit wrdata_lsw formed from 8bit msb and lsb values read from ucode_image */ 859 EFUN(wrc_micro_ra_wrdata_lsw(wrdata_lsw)); /* Program RAM lower 16bits write data */ 860 } while (count < ucode_len_padded); /* Loop repeated till entire image loaded (upto the 4byte boundary) */ 861 862 EFUN(wrc_micro_ra_wrdatasize(0x2)); /* Select 32bit transfers as default */ 863 EFUN(wrc_micro_core_clk_en(0x1)); /* Enable clock to M0 core */ 864 /* EFUN(wrc_micro_core_rstb(0x1)); */ /* De-assert reset to micro to start executing microcode */ 865 return (ERR_CODE_NONE); /* NO Errors while loading microcode (uCode Load PASS) */ 866 } 867 868 869 /* Read-back uCode from Program RAM and verify against ucode_image [Return Val = Error_Code (0 = PASS)] */ 870 err_code_t merlin16_ucode_load_verify(srds_access_t *sa__, uint8_t *ucode_image, uint32_t ucode_len) { 871 872 uint32_t ucode_len_padded, count = 0; 873 uint16_t rddata_lsw; 874 uint16_t data_lsw; 875 uint8_t rddata_lsb; 876 877 if(!ucode_image) { 878 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 879 } 880 881 ucode_len_padded = ((ucode_len + 3) & 0xFFFFFFFC); /* Aligning ucode size to 4-byte boundary */ 882 883 if (ucode_len_padded > UCODE_MAX_SIZE) { /* uCode size should be less than UCODE_MAX_SIZE */ 884 return (_error(ERR_CODE_INVALID_UCODE_LEN)); 885 } 886 887 EFUN(wrc_micro_autoinc_rdaddr_en(0x1)); /* To auto increment RAM read address */ 888 EFUN(wrc_micro_ra_rddatasize(0x1)); /* Select 16bit transfers */ 889 EFUN(wrc_micro_ra_rdaddr_msw(0x0)); /* Upper 16bits of start address of Program RAM from where to read ucode */ 890 EFUN(wrc_micro_ra_rdaddr_lsw(0x0)); /* Lower 16bits of start address of Program RAM from where to read ucode */ 891 892 do { /* ucode_image read 16bits at a time */ 893 rddata_lsb = (count < ucode_len) ? ucode_image[count] : 0x0; /* rddata_lsb read from ucode_image; zero padded to 4byte boundary */ 894 count++; 895 rddata_lsw = (count < ucode_len) ? ucode_image[count] : 0x0; /* rddata_msb read from ucode_image; zero padded to 4byte boundary */ 896 count++; 897 rddata_lsw = ((rddata_lsw << 8) | rddata_lsb); /* 16bit rddata_lsw formed from 8bit msb and lsb values read from ucode_image */ 898 /* Compare Program RAM ucode to ucode_image (Read to micro_ra_rddata_lsw reg auto-increments the ram_address) */ 899 ESTM(data_lsw = rdc_micro_ra_rddata_lsw()); 900 if (data_lsw != rddata_lsw) { 901 EFUN_PRINTF(("Ucode_Load_Verify_FAIL: Addr = 0x%x: Read_data = 0x%x : Expected_data = 0x%x \n",(count-2),data_lsw,rddata_lsw)); 902 return (_error(ERR_CODE_UCODE_VERIFY_FAIL)); /* Verify uCode FAIL */ 903 } 904 905 } while (count < ucode_len_padded); /* Loop repeated till entire image loaded (upto the 4byte boundary) */ 906 907 EFUN(wrc_micro_ra_rddatasize(0x2)); /* Select 32bit transfers ad default */ 908 return (ERR_CODE_NONE); /* Verify uCode PASS */ 909 } 910 911 /******************************************************************/ 912 /* APIs to Align TX clocks */ 913 /******************************************************************/ 914 err_code_t merlin16_tx_clock_align(srds_access_t *sa__, int num_lanes, int enable) { 915 int current_lane, lane; 916 917 ESTM(current_lane = merlin16_get_lane(sa__)); 918 919 for(lane = 0;lane<num_lanes;++lane) { 920 EFUN(merlin16_set_lane(sa__,lane)); 921 if(enable) { 922 if(lane == current_lane) { /* Current Lane should be the master lane */ 923 EFUN(wr_ams_tx_sel_txmaster(1)); /* Select one lane as txmaster. For all other lanes, this should be 0. */ 924 EFUN(wr_ams_tx_pd_phasedet(0)); /* 1 - TCA PD powerdown, 0 - enable PD (enable only for the slave lanes) */ 925 } else { 926 /* Initial TX lane clock phase alignment. Program following registers only for slave lanes, master lane registers should not be programmed (can be kept in default values). */ 927 EFUN(wr_tx_pi_pd_bypass_vco(1)); /* for quick phase lock time */ 928 EFUN(wr_tx_pi_pd_bypass_flt(1)); /* for quick phase lock time */ 929 EFUN(wr_tx_pi_ext_pd_sel(0)); /* selects PD path based on tx_pi_repeater_mode_en */ 930 EFUN(wr_tx_pi_repeater_mode_en(1)); /* selects external PD from afe as input to tx_pi */ 931 EFUN(wr_tx_pi_en(1)); /* Enable TX_PI */ 932 EFUN(wr_tx_pi_jitter_filter_en(0)); /* turn off frequency lock for tx_pi as all te tclk clocks are derived from VCO and same frequency */ 933 EFUN(wr_tx_pi_ext_ctrl_en(1)); /* turn on PD path to TX_PI to lock the clocks */ 934 EFUN(USR_DELAY_US(25)); /* wait for the slave lane clocks to lock to the master lane clock */ 935 EFUN(wr_tx_pi_ext_phase_bwsel_integ(3)); /* 0 to 7: higher value means faster lock time */ 936 EFUN(wr_tx_pi_pd_bypass_vco(0)); /* disable filter bypass for more accurate lock */ 937 EFUN(wr_tx_pi_pd_bypass_flt(0)); /* disable filter bypass for more accurate lock */ 938 EFUN(USR_DELAY_US(60)); /* wait for the slave lane clocks to lock to the master lane clock withing 1/16th of UI. */ 939 /* that all TX lane clocks are correct frequency and aligned together within 1/16th of UI. */ 940 } 941 942 } else { 943 if(lane == current_lane) { /* Current Lane should be the master lane */ 944 EFUN(wr_ams_tx_sel_txmaster(0)); /* Select one lane as txmaster. For all other lanes, this should be 0. */ 945 EFUN(wr_ams_tx_pd_phasedet(1)); /* 1 - TCA PD powerdown, 0 - enable PD (enable only for the slave lanes) */ 946 } else { 947 /* Initial TX lane clock phase alignment. Program following registers only for slave lanes, master lane registers should not be programmed (can be kept in default values). */ 948 EFUN(wr_tx_pi_pd_bypass_vco(0)); /* for quick phase lock time */ 949 EFUN(wr_tx_pi_pd_bypass_flt(0)); /* for quick phase lock time */ 950 EFUN(wr_tx_pi_ext_pd_sel(0)); /* selects PD path based on tx_pi_repeater_mode_en */ 951 EFUN(wr_tx_pi_repeater_mode_en(1)); /* selects external PD from afe as input to tx_pi */ 952 EFUN(wr_tx_pi_en(0)); /* Enable TX_PI */ 953 EFUN(wr_tx_pi_jitter_filter_en(0)); /* turn off frequency lock for tx_pi as all te tclk clocks are derived from VCO and same frequency */ 954 EFUN(wr_tx_pi_ext_ctrl_en(0)); /* turn on PD path to TX_PI to lock the clocks */ 955 EFUN(wr_tx_pi_ext_phase_bwsel_integ(0)); /* 0 to 7: higher value means faster lock time */ 956 EFUN(wr_tx_pi_pd_bypass_vco(0)); /* disable filter bypass for more accurate lock */ 957 /* that all TX lane clocks are correct frequency and aligned together within 1/16th of UI. */ 958 } 959 960 } 961 } 962 EFUN(merlin16_set_lane(sa__,current_lane)); /* return lane to previous state */ 963 return(ERR_CODE_NONE); 964 } 965 966 967