modular.c (22229B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: modular.c 8 * 9 * Purpose: 10 * 11 * Functions: 12 * bcm_common_ptp_modular_enable_get 13 * bcm_common_ptp_modular_enable_set 14 * bcm_common_ptp_modular_phyts_get 15 * bcm_common_ptp_modular_phyts_set 16 * bcm_common_ptp_modular_portbitmap_get 17 * bcm_common_ptp_modular_portbitmap_set 18 * bcm_common_ptp_modular_verbose_get 19 * bcm_common_ptp_modular_verbose_set 20 * 21 * _bcm_ptp_modular_init 22 * _bcm_ptp_modular_shutdown 23 * _bcm_ptp_modular_supervisor 24 * _bcm_ptp_modular_physync_synchronize 25 * _bcm_ptp_modular_physync_configure 26 */ 27 28 #if defined(INCLUDE_PTP) 29 30 #include <shared/util.h> 31 #include <bcm/ptp.h> 32 #include <bcm_int/common/ptp.h> 33 #include <bcm_int/ptp_common.h> 34 35 #include <bcm/port.h> 36 37 #include <bcm/error.h> 38 39 #include <soc/dport.h> 40 41 /* Definitions. */ 42 #define PTP_MODULAR_SUPERVISOR_DPC_TIME_USEC_DEFAULT (1000000) 43 #define PTP_MODULAR_SUPERVISOR_DPC_TIME_USEC_IDLE (3000000) 44 #define PTP_MODULAR_PHYSYNC_FRAMESYNC_WAIT_USEC (1000) 45 46 #define PTP_MODULAR_PHYSYNC_REFPHASE_OFFSET_SEC (1) 47 48 #define PTP_MODULAR_PHYSYNC_FREQUENCY_PIN (-1) 49 #define PTP_MODULAR_PHYSYNC_FRAMESYNC_PIN (3) 50 51 /* Macros. */ 52 53 /* Types. */ 54 typedef struct _bcm_ptp_modular_options_s { 55 int enable; 56 int verbose; 57 int phyts; 58 int framesync_pin; 59 bcm_pbmp_t pbmp; 60 } _bcm_ptp_modular_options_t; 61 62 /* Constants and variables. */ 63 static _bcm_ptp_modular_options_t modular_options = { 64 0, 65 0, 66 0, 67 0, 68 {{0x00000000}} 69 }; 70 71 static uint32 modular_flags; 72 static shr_rdpc_t modular_supervisor_rdpc; 73 74 /* Static functions. */ 75 static sal_usecs_t _bcm_ptp_modular_supervisor( 76 void **arg_unit, void **arg_ptp_id, 77 void **arg_clock_num, void **unused); 78 79 static int _bcm_ptp_modular_physync_synchronize( 80 int unit, bcm_ptp_stack_id_t ptp_id, int clock_num); 81 82 static int _bcm_ptp_modular_physync_configure( 83 int unit, bcm_port_t port, uint64 ref_phase); 84 85 /* 86 * Function: 87 * _bcm_ptp_modular_init 88 * Purpose: 89 * Initialize the modular system. 90 * Parameters: 91 * unit - (IN) Unit number. 92 * ptp_id - (IN) PTP stack ID. 93 * clock_num - (IN) PTP clock number. 94 * flags - (IN) Modular system control flags. (UNUSED) 95 * Returns: 96 * BCM_E_XXX - Function status. 97 * Notes: 98 */ 99 int 100 _bcm_ptp_modular_init( 101 int unit, 102 bcm_ptp_stack_id_t ptp_id, 103 int clock_num, 104 uint32 flags) 105 { 106 int rv; 107 108 if (shr_rdpc_callback_created(&modular_supervisor_rdpc) == BCM_E_INIT) { 109 /* RDPC (and associated lock) is left in place on cleanup, so only create it once */ 110 rv = shr_rdpc_callback_create(&modular_supervisor_rdpc, &_bcm_ptp_modular_supervisor); 111 } else { 112 rv = shr_rdpc_callback_stop(&modular_supervisor_rdpc); 113 } 114 return rv; 115 } 116 117 /* 118 * Function: 119 * _bcm_ptp_modular_shutdown 120 * Purpose: 121 * Shut down the modular system. 122 * Parameters: 123 * unit - (IN) Unit number. 124 * ptp_id - (IN) PTP stack ID. 125 * clock_num - (IN) PTP clock number. 126 * Returns: 127 * BCM_E_XXX - Function status. 128 * Notes: 129 */ 130 int 131 _bcm_ptp_modular_shutdown( 132 int unit, 133 bcm_ptp_stack_id_t ptp_id, 134 int clock_num) 135 { 136 int rv; 137 /* Cancel modular system supervisor repeating delayed procedure call. */ 138 rv = shr_rdpc_callback_stop(&modular_supervisor_rdpc); 139 return rv; 140 } 141 142 /* 143 * Function: 144 * bcm_common_ptp_modular_enable_get 145 * Purpose: 146 * Get enable/disable state of modular system functionality. 147 * Parameters: 148 * unit - (IN) Unit number. 149 * ptp_id - (IN) PTP stack ID. 150 * clock_num - (IN) PTP clock number. 151 * enable - (OUT) Enable Boolean. 152 * flags - (OUT) Modular system control flags. (UNUSED) 153 * Returns: 154 * BCM_E_XXX - Function status. 155 * Notes: 156 */ 157 int 158 bcm_common_ptp_modular_enable_get( 159 int unit, 160 bcm_ptp_stack_id_t ptp_id, 161 int clock_num, 162 int *enable, 163 uint32 *flags) 164 { 165 int rv; 166 167 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 168 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 169 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 170 return rv; 171 } 172 173 *enable = modular_options.enable; 174 *flags = modular_flags; 175 176 return BCM_E_NONE; 177 } 178 179 /* 180 * Function: 181 * bcm_common_ptp_modular_enable_set 182 * Purpose: 183 * Set enable/disable state of modular system functionality. 184 * Parameters: 185 * unit - (IN) Unit number. 186 * ptp_id - (IN) PTP stack ID. 187 * clock_num - (IN) PTP clock number. 188 * enable - (IN) Enable Boolean. 189 * flags - (IN) Modular system control flags. (UNUSED) 190 * Returns: 191 * BCM_E_XXX - Function status. 192 * Notes: 193 */ 194 int 195 bcm_common_ptp_modular_enable_set( 196 int unit, 197 bcm_ptp_stack_id_t ptp_id, 198 int clock_num, 199 int enable, 200 uint32 flags) 201 { 202 int rv; 203 int i; 204 205 uint8 payload[PTP_MGMTMSG_PAYLOAD_TELECOM_PROFILE_ENABLED_SIZE_OCTETS] = {0}; 206 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 207 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 208 209 bcm_ptp_port_identity_t portid; 210 211 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 212 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 213 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 214 return rv; 215 } 216 217 /* 218 * Make payload. 219 * Octet 0...5 : Custom management message key/identifier. 220 * BCM<null><null><null>. 221 * Octet 6 : Modular system enabled Boolean. 222 * Octet 7 : Reserved. 223 */ 224 sal_memcpy(payload, "BCM\0\0\0", 6); 225 i = 6; 226 payload[i] = enable ? 1:0; 227 228 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 229 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 230 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 231 return rv; 232 } 233 234 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, 235 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_MODULAR_SYSTEM_ENABLED, 236 payload, PTP_MGMTMSG_PAYLOAD_MODULAR_SYSTEM_ENABLED_SIZE_OCTETS, 237 resp, &resp_len))) { 238 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 239 return rv; 240 } 241 242 /* Start modular system supervisor DPC iff modular system is enabled. */ 243 if (enable) { 244 rv = shr_rdpc_callback_start(&modular_supervisor_rdpc, PTP_MODULAR_SUPERVISOR_DPC_TIME_USEC_DEFAULT, 245 INT_TO_PTR(unit), INT_TO_PTR(ptp_id), INT_TO_PTR(clock_num), 0); 246 } else { 247 rv = shr_rdpc_callback_stop(&modular_supervisor_rdpc); 248 } 249 250 modular_options.enable = enable; 251 modular_flags = flags; 252 253 return BCM_E_NONE; 254 } 255 256 /* 257 * Function: 258 * bcm_common_ptp_modular_verbose_get 259 * Purpose: 260 * Get verbose program control option of modular system functionality. 261 * Parameters: 262 * unit - (IN) Unit number. 263 * ptp_id - (IN) PTP stack ID. 264 * clock_num - (IN) PTP clock number. 265 * verbose - (OUT) Verbose Boolean. 266 * Returns: 267 * BCM_E_XXX - Function status. 268 * Notes: 269 */ 270 int 271 bcm_common_ptp_modular_verbose_get( 272 int unit, 273 bcm_ptp_stack_id_t ptp_id, 274 int clock_num, 275 int *verbose) 276 { 277 int rv; 278 279 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 280 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 281 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 282 return rv; 283 } 284 285 *verbose = modular_options.verbose; 286 return BCM_E_NONE; 287 } 288 289 /* 290 * Function: 291 * bcm_common_ptp_modular_verbose_set 292 * Purpose: 293 * Set verbose program control option of modular system functionality. 294 * Parameters: 295 * unit - (IN) Unit number. 296 * ptp_id - (IN) PTP stack ID. 297 * clock_num - (IN) PTP clock number. 298 * verbose - (IN) Verbose Boolean. 299 * Returns: 300 * BCM_E_XXX - Function status. 301 * Notes: 302 */ 303 int 304 bcm_common_ptp_modular_verbose_set( 305 int unit, 306 bcm_ptp_stack_id_t ptp_id, 307 int clock_num, 308 int verbose) 309 { 310 int rv; 311 312 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 313 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 314 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 315 return rv; 316 } 317 318 modular_options.verbose = verbose; 319 return BCM_E_NONE; 320 } 321 322 /* 323 * Function: 324 * bcm_common_ptp_modular_portbitmap_get 325 * Purpose: 326 * Get PHY port bitmap. 327 * Parameters: 328 * unit - (IN) Unit number. 329 * ptp_id - (IN) PTP stack ID. 330 * clock_num - (IN) PTP clock number. 331 * pbmp - (OUT) Port bitmap. 332 * Returns: 333 * BCM_E_XXX - Function status. 334 * Notes: 335 */ 336 int 337 bcm_common_ptp_modular_portbitmap_get( 338 int unit, 339 bcm_ptp_stack_id_t ptp_id, 340 int clock_num, 341 bcm_pbmp_t *pbmp) 342 { 343 int rv; 344 345 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 346 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 347 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 348 return rv; 349 } 350 351 *pbmp = modular_options.pbmp; 352 return BCM_E_NONE; 353 } 354 355 /* 356 * Function: 357 * bcm_common_ptp_modular_portbitmap_set 358 * Purpose: 359 * Set PHY port bitmap. 360 * Parameters: 361 * unit - (IN) Unit number. 362 * ptp_id - (IN) PTP stack ID. 363 * clock_num - (IN) PTP clock number. 364 * pbmp - (IN) Port bitmap. 365 * Returns: 366 * BCM_E_XXX - Function status. 367 * Notes: 368 */ 369 int 370 bcm_common_ptp_modular_portbitmap_set( 371 int unit, 372 bcm_ptp_stack_id_t ptp_id, 373 int clock_num, 374 bcm_pbmp_t pbmp) 375 { 376 int rv; 377 378 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 379 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 380 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 381 return rv; 382 } 383 384 modular_options.pbmp = pbmp; 385 return BCM_E_NONE; 386 } 387 388 /* 389 * Function: 390 * bcm_common_ptp_modular_phyts_get 391 * Purpose: 392 * Get PHY timestamping configuration state and data. 393 * Parameters: 394 * unit - (IN) Unit number. 395 * ptp_id - (IN) PTP stack ID. 396 * clock_num - (IN) PTP clock number. 397 * phyts - (OUT) PHY timestamping Boolean. 398 * framesync_pin - (OUT) Framesync GPIO pin. 399 * Returns: 400 * BCM_E_XXX - Function status. 401 * Notes: 402 */ 403 int 404 bcm_common_ptp_modular_phyts_get( 405 int unit, 406 bcm_ptp_stack_id_t ptp_id, 407 int clock_num, 408 int *phyts, 409 int *framesync_pin) 410 { 411 int rv; 412 413 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 414 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 415 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 416 return rv; 417 } 418 419 *phyts = modular_options.phyts; 420 *framesync_pin = modular_options.framesync_pin; 421 return BCM_E_NONE; 422 } 423 424 /* 425 * Function: 426 * bcm_common_ptp_modular_phyts_set 427 * Purpose: 428 * Set PHY timestamping configuration state and data. 429 * Parameters: 430 * unit - (IN) Unit number. 431 * ptp_id - (IN) PTP stack ID. 432 * clock_num - (IN) PTP clock number. 433 * phyts - (IN) PHY timestamping Boolean. 434 * framesync_pin - (IN) Framesync GPIO pin. 435 * Returns: 436 * BCM_E_XXX - Function status. 437 * Notes: 438 */ 439 int 440 bcm_common_ptp_modular_phyts_set( 441 int unit, 442 bcm_ptp_stack_id_t ptp_id, 443 int clock_num, 444 int phyts, 445 int framesync_pin) 446 { 447 int rv; 448 449 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 450 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 451 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 452 return rv; 453 } 454 455 modular_options.phyts = phyts; 456 modular_options.framesync_pin = framesync_pin; 457 return BCM_E_NONE; 458 } 459 460 /* 461 * Function: 462 * _bcm_ptp_modular_supervisor 463 * Purpose: 464 * Run modular system supervisor (as RDPC). 465 * Parameters: 466 * arg_unit - (IN) Unit number (as void**). 467 * arg_ptp_id - (IN) PTP stack ID (as void**). 468 * arg_clock_num - (IN) PTP clock number (as void**). 469 * unused - (IN) Unused. 470 * Returns: 471 * Interval before next call 472 * Notes: 473 */ 474 static sal_usecs_t 475 _bcm_ptp_modular_supervisor( 476 void **arg_unit, 477 void **arg_ptp_id, 478 void **arg_clock_num, 479 void **unused) 480 { 481 int rv; 482 483 int unit = PTR_TO_INT(*arg_unit); 484 bcm_ptp_stack_id_t ptp_id = (bcm_ptp_stack_id_t)PTR_TO_INT(*arg_ptp_id); 485 int clock_num = PTR_TO_INT(*arg_clock_num); 486 487 if (0 == modular_options.phyts) { 488 /* IDLE. PHY timestamping option is not currently set. */ 489 return PTP_MODULAR_SUPERVISOR_DPC_TIME_USEC_IDLE; 490 } else if (BCM_FAILURE(rv = _bcm_ptp_modular_physync_synchronize(unit, ptp_id, clock_num))) { 491 PTP_ERROR_FUNC("_bcm_ptp_modular_physync_synchronize()"); 492 return PTP_MODULAR_SUPERVISOR_DPC_TIME_USEC_IDLE; 493 } else { 494 return PTP_MODULAR_SUPERVISOR_DPC_TIME_USEC_DEFAULT; 495 } 496 } 497 498 /* 499 * Function: 500 * _bcm_ptp_modular_physync_synchronize 501 * Purpose: 502 * Synchronize PHYs. 503 * Parameters: 504 * unit - (IN) Unit number. 505 * ptp_id - (IN) PTP stack ID. 506 * clock_num - (IN) PTP clock number. 507 * Returns: 508 * BCM_E_XXX - Function status. 509 * Notes: 510 */ 511 static int 512 _bcm_ptp_modular_physync_synchronize( 513 int unit, 514 bcm_ptp_stack_id_t ptp_id, 515 int clock_num) 516 { 517 int rv; 518 int i; 519 520 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 521 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 522 523 bcm_ptp_port_identity_t portid; 524 525 uint8 physync_reqd = 0; 526 uint64 localTime_sec; 527 uint32 localTime_nsec; 528 uint64 physyncTime_nsec; 529 530 soc_port_t p, dport; 531 bcm_ptp_sync_phy_input_t physync_input; 532 533 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 534 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 535 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 536 return rv; 537 } 538 539 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 540 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 541 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 542 return rv; 543 } 544 545 /* Query stack to determine whether PHY synchronization is required. */ 546 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 547 clock_num, &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_PHYSYNC_STATE, 548 0, 0, resp, &resp_len))) { 549 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 550 return rv; 551 } 552 553 /* 554 * Parse response. 555 * Octet 0...5 : Custom management message key/identifier. 556 * BCM<null><null><null>. 557 * Octet 6 : PHY synchronization required Boolean. 558 * Octet 7 : Reserved. 559 * Octet 8...15 : Stack local time (sec). 560 * Octet 16...19: stack local time (nsec). 561 */ 562 i = 6; /* Advance cursor past custom management message identifier. */ 563 physync_reqd = resp[i++]; 564 i++; /* Advance cursor past reserved octet. */ 565 566 localTime_sec = _bcm_ptp_uint64_read(resp + i); 567 i += 8; 568 localTime_nsec = _bcm_ptp_uint32_read(resp + i); 569 570 /* PHY synchronization. */ 571 if (0 == physync_reqd) { 572 /* PHY synchronization is not required. */ 573 return rv; 574 } 575 576 /* 577 * PHY synchronization. 578 * Calculate reference phase to program PHYs. 579 * Reference phase based on local time (i.e. when stack is queried for 580 * PHY synchronization state) plus sufficient delta to guarantee stack 581 * can receive and process PHY framesync at BSHB which corresponds to 582 * programmed phase. 583 * 584 * NOTE: Reference phase is quantized in microsecond to align with BSHB. 585 * Katana timing card PHY synchronization integrated with BSHB TS 586 * processing and has access to full-rate (4KHz) BSHB interrupts. 587 * Keystone timing card PHY synchronization integrated with BSHB 588 * DPLL and hass access to 1KHz timestamps for DPLL update. 589 */ 590 physyncTime_nsec = localTime_sec; 591 COMPILER_64_ADD_32(physyncTime_nsec, PTP_MODULAR_PHYSYNC_REFPHASE_OFFSET_SEC); 592 COMPILER_64_UMUL_32(physyncTime_nsec, 1000000000); 593 COMPILER_64_ADD_32(physyncTime_nsec, ((localTime_nsec+500000)/1000000)*1000000); 594 595 /* 596 * PHY synchronization. 597 * Trigger/stage framesync. 598 * Program reference phase. 599 * Send framesync (FW initiated GPIO high/low @ prescribed time). 600 */ 601 602 physync_input.framesync_pin = modular_options.framesync_pin > 0 ? 603 modular_options.framesync_pin : PTP_MODULAR_PHYSYNC_FRAMESYNC_PIN; 604 physync_input.freq_pin= PTP_MODULAR_PHYSYNC_FREQUENCY_PIN; 605 physync_input.reference_time = physyncTime_nsec; 606 607 /* Initial framesync. Pull pin low. */ 608 if (BCM_FAILURE(rv = bcm_common_ptp_sync_phy(unit, ptp_id, clock_num, physync_input))) { 609 PTP_ERROR_FUNC("bcm_common_ptp_sync_phy()"); 610 return rv; 611 } 612 613 /* Wait. Allow initial framesync to occur. */ 614 sal_usleep(PTP_MODULAR_PHYSYNC_FRAMESYNC_WAIT_USEC); 615 616 /* coverity[overrun-local] */ 617 SOC_DPORT_PBMP_ITER(unit, modular_options.pbmp, dport, p) { 618 if (BCM_FAILURE(rv = _bcm_ptp_modular_physync_configure(unit, p, physyncTime_nsec))) { 619 PTP_ERROR_FUNC("_bcm_ptp_modular_physync_configure()"); 620 return rv; 621 } 622 } 623 624 /* Actual framesync. Load PHY values. */ 625 if (BCM_FAILURE(rv = bcm_common_ptp_sync_phy(unit, ptp_id, clock_num, physync_input))) { 626 PTP_ERROR_FUNC("bcm_common_ptp_sync_phy()"); 627 return rv; 628 } 629 630 return BCM_E_NONE; 631 } 632 633 /* 634 * Function: 635 * _bcm_ptp_modular_physync_configure 636 * Purpose: 637 * Configure PHY port to track 4KHz SYNC_IN0 with framesync on GPIO pin. 638 * Parameters: 639 * unit - (IN) Unit number. 640 * port - (IN) Port. 641 * ref_phase - (IN) Reference phase. 642 * Returns: 643 * BCM_E_XXX - Function status. 644 * Notes: 645 */ 646 static int 647 _bcm_ptp_modular_physync_configure( 648 int unit, 649 bcm_port_t port, 650 uint64 ref_phase) 651 { 652 int rv; 653 bcm_port_phy_timesync_config_t config; 654 uint64 load_control; 655 656 uint64 localTime; 657 658 sal_memset(&config, 0, sizeof(config)); 659 660 config.validity_mask = BCM_PORT_PHY_TIMESYNC_VALID_FLAGS | BCM_PORT_PHY_TIMESYNC_VALID_GMODE | 661 BCM_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE | BCM_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE | 662 BCM_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE | 663 BCM_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE | 664 BCM_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE | BCM_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE | 665 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE | 666 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA | 667 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1 | BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2 | 668 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3 | 669 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_LOOP_FILTER; 670 671 config.flags = BCM_PORT_PHY_TIMESYNC_ENABLE | 672 BCM_PORT_PHY_TIMESYNC_L2_ENABLE | 673 BCM_PORT_PHY_TIMESYNC_IP4_ENABLE | 674 BCM_PORT_PHY_TIMESYNC_IP6_ENABLE | 675 BCM_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT; 676 677 config.gmode = bcmPortPhyTimesyncModeCpu; 678 config.framesync.mode = bcmPortPhyTimesyncFramesyncSyncin1; 679 config.syncout.mode = bcmPortPhyTimesyncSyncoutDisable; 680 config.tx_sync_mode = bcmPortPhyTimesyncEventMessageEgressModeUpdateCorrectionField; 681 config.rx_sync_mode = bcmPortPhyTimesyncEventMessageIngressModeUpdateCorrectionField; 682 config.tx_delay_request_mode = bcmPortPhyTimesyncEventMessageEgressModeUpdateCorrectionField; 683 config.rx_delay_request_mode = bcmPortPhyTimesyncEventMessageIngressModeUpdateCorrectionField; 684 /* for 4KHz SyncIn */ 685 config.phy_1588_dpll_ref_phase = ref_phase; 686 config.phy_1588_dpll_ref_phase_delta = 250000; 687 config.phy_1588_dpll_k1 = 0x2b; 688 config.phy_1588_dpll_k2 = 0x26; 689 config.phy_1588_dpll_k3 = 0; 690 691 /* Initial value for the loop filter: 0x8000 0000 0000 0000 */ 692 COMPILER_64_SET(config.phy_1588_dpll_loop_filter, 0x80000000, 0); 693 694 if (BCM_FAILURE(rv = bcm_port_phy_timesync_config_set(unit, port, &config))) { 695 PTP_ERROR_FUNC("bcm_port_phy_timesync_config_set()"); 696 return rv; 697 } 698 699 /* 700 * Set local time (use reference phase). 701 * NOTE: Empirically, programmed PHY timesync local time has scale factor 702 * of 16 compared to argument specified in nanoseconds. 703 * PHY data sheet mentions registers 2a,2b,2c to set 44 MSBs of PHY 704 * local timestamper. Control of upper 44 bits of 48-bit local time 705 * likely accounts for 4-bit (16x) scaling required to set the PHY 706 * local time with nanoseconds reference phase via following API. 707 */ 708 localTime = _bcm_ptp_llu_div(ref_phase, 16); 709 if (BCM_FAILURE(rv = bcm_port_control_phy_timesync_set(unit, port, 710 bcmPortControlPhyTimesyncLocalTime, localTime))) { 711 PTP_ERROR_FUNC("bcm_port_control_phy_timesync_set()"); 712 return rv; 713 } 714 715 COMPILER_64_SET(load_control, 0, 716 BCM_PORT_PHY_TIMESYNC_TN_LOAD | 717 BCM_PORT_PHY_TIMESYNC_TIMECODE_LOAD | 718 BCM_PORT_PHY_TIMESYNC_SYNCOUT_LOAD | 719 BCM_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD | 720 BCM_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD | 721 BCM_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD | 722 BCM_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD | 723 BCM_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD | 724 BCM_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD | 725 BCM_PORT_PHY_TIMESYNC_DPLL_K3_LOAD | 726 BCM_PORT_PHY_TIMESYNC_DPLL_K2_LOAD | 727 BCM_PORT_PHY_TIMESYNC_DPLL_K1_LOAD ); 728 729 /* Set load control. */ 730 if (BCM_FAILURE(rv = bcm_port_control_phy_timesync_set(unit, port, 731 bcmPortControlPhyTimesyncLoadControl, load_control))) { 732 PTP_ERROR_FUNC("bcm_port_control_phy_timesync_set()"); 733 return rv; 734 } 735 736 return BCM_E_NONE; 737 } 738 739 #endif /* defined(INCLUDE_PTP) */