servo.c (56049B)
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: servo.c 8 * 9 * Purpose: 10 * 11 * Functions: 12 * bcm_common_ptp_servo_configuration_get 13 * bcm_common_ptp_servo_configuration_set 14 * bcm_common_ptp_servo_status_get 15 * bcm_common_ptp_phase_offset_set 16 * bcm_common_ptp_phase_offset_get 17 * 18 * _bcm_ptp_servo_start 19 * _bcm_ptp_servo_restart 20 * _bcm_ptp_servo_stop 21 * _bcm_ptp_servo_ipdv_configuration_get 22 * _bcm_ptp_servo_ipdv_configuration_set 23 * _bcm_ptp_servo_performance_get 24 * _bcm_ptp_servo_ipdv_performance_get 25 * _bcm_ptp_servo_performance_data_clear 26 */ 27 28 #if defined(INCLUDE_PTP) 29 30 #include <bcm/ptp.h> 31 #include <bcm_int/common/ptp.h> 32 #include <bcm_int/ptp_common.h> 33 #include <bcm/error.h> 34 35 static const bcm_ptp_port_identity_t portid_all = 36 {{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, PTP_IEEE1588_ALL_PORTS}; 37 38 /* 39 * Function: 40 * _bcm_ptp_servo_start 41 * Purpose: 42 * Start PTP time synchronization servo. 43 * Parameters: 44 * unit - (IN) Unit number. 45 * ptp_id - (IN) PTP stack ID. 46 * clock_num - (IN) PTP clock number. 47 * Returns: 48 * BCM_E_XXX - Function status. 49 * Notes: 50 */ 51 int 52 _bcm_ptp_servo_start( 53 int unit, 54 bcm_ptp_stack_id_t ptp_id, 55 int clock_num) 56 { 57 int rv = BCM_E_UNAVAIL; 58 59 uint8 payload[PTP_MGMTMSG_PAYLOAD_MIN_PROPRIETARY_MSG_SIZE_OCTETS] = {0}; 60 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 61 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 62 int i = 0; 63 64 bcm_ptp_port_identity_t portid; 65 66 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 67 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 68 return rv; 69 } 70 71 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 72 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 73 /* On error, target message to (all clocks, all ports) portIdentity. */ 74 portid = portid_all; 75 } 76 77 /* 78 * Make payload. 79 * Octet 0...5 : Custom management message key/identifier. 80 * BCM<null><null><null>. 81 */ 82 i = 0; 83 payload[i++] = 'B'; 84 payload[i++] = 'C'; 85 payload[i++] = 'M'; 86 87 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, 88 &portid, PTP_MGMTMSG_CMD, PTP_MGMTMSG_ID_SERVO_START, 89 payload, PTP_MGMTMSG_PAYLOAD_MIN_PROPRIETARY_MSG_SIZE_OCTETS, 90 resp, &resp_len); 91 92 return rv; 93 } 94 95 /* 96 * Function: 97 * _bcm_ptp_servo_restart 98 * Purpose: 99 * Restart PTP time synchronization servo. 100 * Parameters: 101 * unit - (IN) Unit number. 102 * ptp_id - (IN) PTP stack ID. 103 * clock_num - (IN) PTP clock number. 104 * Returns: 105 * BCM_E_XXX - Function status. 106 * Notes: 107 */ 108 int 109 _bcm_ptp_servo_restart( 110 int unit, 111 bcm_ptp_stack_id_t ptp_id, 112 int clock_num) 113 { 114 /* Note: this is currently a No-op in the servo */ 115 int rv = BCM_E_UNAVAIL; 116 117 uint8 payload[PTP_MGMTMSG_PAYLOAD_MIN_PROPRIETARY_MSG_SIZE_OCTETS] = {0}; 118 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 119 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 120 int i = 0; 121 122 bcm_ptp_port_identity_t portid; 123 124 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 125 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 126 return rv; 127 } 128 129 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 130 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 131 /* On error, target message to (all clocks, all ports) portIdentity. */ 132 portid = portid_all; 133 } 134 135 /* 136 * Make payload. 137 * Octet 0...5 : Custom management message key/identifier. 138 * BCM<null><null><null>. 139 */ 140 i = 0; 141 payload[i++] = 'B'; 142 payload[i++] = 'C'; 143 payload[i++] = 'M'; 144 145 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, 146 &portid, PTP_MGMTMSG_CMD, PTP_MGMTMSG_ID_SERVO_RESTART, 147 payload, PTP_MGMTMSG_PAYLOAD_MIN_PROPRIETARY_MSG_SIZE_OCTETS, 148 resp, &resp_len); 149 150 return rv; 151 } 152 153 /* 154 * Function: 155 * _bcm_ptp_servo_stop 156 * Purpose: 157 * Stop PTP time synchronization servo. 158 * Parameters: 159 * unit - (IN) Unit number. 160 * ptp_id - (IN) PTP stack ID. 161 * clock_num - (IN) PTP clock number. 162 * Returns: 163 * BCM_E_XXX - Function status. 164 * Notes: 165 */ 166 int 167 _bcm_ptp_servo_stop( 168 int unit, 169 bcm_ptp_stack_id_t ptp_id, 170 int clock_num) 171 { 172 173 /* Firmware does not support SERVO STOP. */ 174 return BCM_E_UNAVAIL; 175 } 176 177 /* 178 * Function: 179 * bcm_common_ptp_servo_configuration_get 180 * Purpose: 181 * Get PTP servo configuration properties. 182 * Parameters: 183 * unit - (IN) Unit number. 184 * ptp_id - (IN) PTP stack ID. 185 * clock_num - (IN) PTP clock number. 186 * config - (OUT) PTP servo configuration properties. 187 * Returns: 188 * BCM_E_XXX - Function status. 189 * Notes: 190 */ 191 int 192 bcm_common_ptp_servo_configuration_get( 193 int unit, 194 bcm_ptp_stack_id_t ptp_id, 195 int clock_num, 196 bcm_ptp_servo_config_t *config) 197 { 198 int rv = BCM_E_UNAVAIL; 199 200 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 201 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 202 int i = 0; 203 204 bcm_ptp_port_identity_t portid; 205 206 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 207 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 208 return rv; 209 } 210 211 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 212 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 213 /* On error, target message to (all clocks, all ports) portIdentity. */ 214 portid = portid_all; 215 } 216 217 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 218 clock_num, &portid, 219 PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_SERVO_CONFIGURATION, 220 0, 0, resp, &resp_len))) { 221 return rv; 222 } 223 224 225 /* 226 * Parse response. 227 * Octet 0...5 : Custom management message key/identifier. 228 * BCM<null><null><null>. 229 * Octet 6...9 : Oscillator type. 230 * Octet 10...13 : PTP transport mode. 231 * Octet 14...17 : Phase Mode. 232 * Octet 18...21 : Freq. correction sampled hourly (times 1E+12). 233 * Octet 22...29 : Timestamp of freq. correction measurement (sec). 234 * Octet 30...33 : Timestamp of freq. correction measurement (nsec). 235 * Octet 34...37 : Flags 236 * Octet 38...45 : RFU 237 * Octet 46...49 : RFU 238 * Octet 50...53 : Bridge time. 239 * Octet 54...57 : Filter Profile 240 */ 241 i = 6; 242 config->osc_type = (bcm_ptp_osc_type_t)_bcm_ptp_uint32_read(resp+i); 243 i += sizeof(uint32); 244 config->transport_mode = (bcm_ptp_transport_mode_t)_bcm_ptp_uint32_read(resp+i); 245 i += sizeof(uint32); 246 config->ptp_phase_mode = _bcm_ptp_uint32_read(resp+i); 247 i += sizeof(uint32); 248 config->freq_corr = _bcm_ptp_uint32_read(resp+i); 249 i += sizeof(uint32); 250 config->freq_corr_time.seconds = _bcm_ptp_uint64_read(resp+i); 251 i += sizeof(uint64); 252 config->freq_corr_time.nanoseconds = _bcm_ptp_uint32_read(resp+i); 253 i += sizeof(uint32); 254 config->flags = _bcm_ptp_uint32_read(resp+i); 255 config->servo = (config->flags & 0x0f); 256 config->flags >>= 4; 257 i += sizeof(uint32); 258 /* RFU */ 259 i += sizeof(uint64); 260 /* RFU */ 261 i += sizeof(uint32); 262 config->bridge_time = _bcm_ptp_uint32_read(resp+i); 263 if (resp_len >= PTP_MGMTMSG_PAYLOAD_SERVO_CONFIGURATION_SIZE_OCTETS) { 264 i += sizeof(uint32); 265 config->filter_profile = _bcm_ptp_uint32_read(resp+i); 266 } else { 267 config->filter_profile = 0; 268 } 269 return rv; 270 } 271 272 /* 273 * Function: 274 * bcm_common_ptp_servo_configuration_set 275 * Purpose: 276 * Set PTP servo configuration properties. 277 * Parameters: 278 * unit - (IN) Unit number. 279 * ptp_id - (IN) PTP stack ID. 280 * clock_num - (IN) PTP clock number. 281 * config - (IN) PTP servo configuration properties. 282 * Returns: 283 * BCM_E_XXX - Function status. 284 * Notes: 285 */ 286 int 287 bcm_common_ptp_servo_configuration_set( 288 int unit, 289 bcm_ptp_stack_id_t ptp_id, 290 int clock_num, 291 bcm_ptp_servo_config_t *config) 292 { 293 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 294 bcm_ptp_clock_info_t *clock_info; 295 #endif 296 int rv = BCM_E_UNAVAIL; 297 298 uint8 payload[PTP_MGMTMSG_PAYLOAD_SERVO_CONFIGURATION_SIZE_OCTETS] = {0}; 299 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 300 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 301 int i = 0; 302 303 bcm_ptp_port_identity_t portid; 304 305 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 306 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 307 return rv; 308 } 309 310 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 311 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 312 /* On error, target message to (all clocks, all ports) portIdentity. */ 313 portid = portid_all; 314 } 315 316 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) 317 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 318 /* PTPPP firmware supports only bcm servo */ 319 if (BCM_SUCCESS(rv = _bcm_ptp_check_firmware_exist("PTP_BRCM_SERVO"))) { 320 if (bcmPTPServoTypeBCM != config->servo) { 321 LOG_ERROR(BSL_LS_BCM_COMMON, 322 (BSL_META_U(unit, 323 "PTP Phase profile firmware supports only Broadcom Servo \n"))); 324 return BCM_E_PARAM; 325 } 326 } 327 } 328 329 #endif /* defined(BCM_PTP_INTERNAL_STACK_SUPPORT) */ 330 331 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 332 clock_info = &_bcm_common_ptp_unit_array[unit].stack_array[ptp_id].clock_array[clock_num].clock_info; 333 334 if (PTP_CLOCK_IS_G8275P1_PROF(clock_info) && (bcmPTPServoTypeBCM != config->servo)) 335 { 336 LOG_ERROR(BSL_LS_BCM_COMMON, 337 (BSL_META_U(unit, "Telecom phase profile supported only with Broadcom Servo \n"))); 338 return BCM_E_PARAM; 339 } 340 341 _bcm_common_ptp_unit_array[unit].stack_array[ptp_id].clock_array[clock_num].servo_type = config->servo; 342 if (config->osc_type != bcmPTPOscTypeOCXO) { 343 /* Reinitialize servo w/ updated osc type */ 344 if (BCM_FAILURE(rv = _bcm_ptp_servo_deinit(unit, ptp_id, clock_num))) { 345 PTP_ERROR_FUNC("_bcm_ptp_servo_deinit()"); 346 } 347 if (BCM_FAILURE(rv = _bcm_ptp_servo_init(unit, ptp_id, clock_num, config->osc_type))) { 348 PTP_ERROR_FUNC("_bcm_ptp_servo_init()"); 349 } 350 } 351 else { 352 LOG_INFO(BSL_LS_BCM_PTP, 353 (BSL_META_U(unit, " Servo initialized w/ OCXO\n"))); 354 } 355 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */ 356 357 /* 358 * Make payload. 359 * Octet 0...5 : Custom management message key/identifier. 360 * BCM<null><null><null>. 361 * Octet 6...9 : Oscillator type. 362 * Octet 10...13 : PTP transport mode. 363 * Octet 14...17 : Phase Mode. 364 * Octet 18...21 : Freq. correction sampled hourly (times 1E+12). 365 * Octet 22...29 : Timestamp of freq. correction measurement (sec). 366 * Octet 30...33 : Timestamp of freq. correction measurement (nsec). 367 * Octet 34...37 : Freq. calibration from factory (times 1E+12). 368 * Octet 38...45 : Timestamp of freq. calibration at factory (sec). 369 * Octet 46...49 : Timestamp of freq. calibration at factory (nsec). 370 * Octet 50...53 : Bridge time. 371 * Octet 54...57 : filter profile 372 */ 373 i = 0; 374 payload[i++] = 'B'; 375 payload[i++] = 'C'; 376 payload[i++] = 'M'; 377 i += 3; 378 _bcm_ptp_uint32_write(payload+i, config->osc_type); 379 i += sizeof(uint32); 380 _bcm_ptp_uint32_write(payload+i, config->transport_mode); 381 i += sizeof(uint32); 382 _bcm_ptp_uint32_write(payload+i, config->ptp_phase_mode); 383 i += sizeof(uint32); 384 _bcm_ptp_uint32_write(payload+i, config->freq_corr); 385 i += sizeof(uint32); 386 _bcm_ptp_uint64_write(payload+i, config->freq_corr_time.seconds); 387 i += sizeof(uint64); 388 _bcm_ptp_uint32_write(payload+i, config->freq_corr_time.nanoseconds); 389 i += sizeof(uint32); 390 _bcm_ptp_uint32_write(payload+i, (config->servo | (config->flags << 4))); 391 i += sizeof(uint32); 392 /* RFU */ 393 i += sizeof(uint64); 394 /* RFU */ 395 i += sizeof(uint32); 396 _bcm_ptp_uint32_write(payload+i, config->bridge_time); 397 i += sizeof(uint32); 398 _bcm_ptp_uint32_write(payload+i, config->filter_profile); 399 400 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, 401 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_SERVO_CONFIGURATION, 402 payload, PTP_MGMTMSG_PAYLOAD_SERVO_CONFIGURATION_SIZE_OCTETS, 403 resp, &resp_len); 404 405 return rv; 406 } 407 408 /* 409 * Function: 410 * bcm_common_ptp_servo_threshold_get 411 * Purpose: 412 * Get PTP servo threshold properties. 413 * Parameters: 414 * unit - (IN) Unit number. 415 * ptp_id - (IN) PTP stack ID. 416 * clock_num - (IN) PTP clock number. 417 * threshold - (OUT) PTP servo configuration properties. 418 * Returns: 419 * BCM_E_XXX - Function status. 420 * Notes: 421 */ 422 int 423 bcm_common_ptp_servo_threshold_get( 424 int unit, 425 bcm_ptp_stack_id_t ptp_id, 426 int clock_num, 427 bcm_ptp_servo_threshold_t *threshold) 428 { 429 int rv = BCM_E_UNAVAIL; 430 431 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 432 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 433 int i = 0; 434 435 bcm_ptp_port_identity_t portid; 436 437 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 438 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 439 return rv; 440 } 441 442 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 443 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 444 /* On error, target message to (all clocks, all ports) portIdentity. */ 445 portid = portid_all; 446 } 447 448 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 449 clock_num, &portid, 450 PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_SERVO_THRESHOLD, 451 0, 0, resp, &resp_len))) { 452 return rv; 453 } 454 455 if (resp_len < PTP_MGMTMSG_PAYLOAD_SERVO_THRESHOLD_SIZE_OCTETS) { 456 /* Internal error : message too short to contain correct data. */ 457 return BCM_E_INTERNAL; 458 } 459 460 /* 461 * Parse response. 462 * Octet 0...5 : Custom management message key/identifier. 463 * BCM<null><null><null>. 464 * Octet 6...9 : Frequency Lock Threshold. 465 * Octet 10...13 : Frequency Unlock Threshold. 466 * Octet 14...17 : Phase Lock Threshold. 467 * Octet 18...21 : Phase Unlock Threshold. 468 */ 469 i = 6; 470 threshold->bcmPtpServoThresholdFreqLock = _bcm_ptp_uint32_read(resp+i); 471 i += sizeof(uint32); 472 threshold->bcmPtpServoThresholdFreqUnlock = _bcm_ptp_uint32_read(resp+i); 473 i += sizeof(uint32); 474 threshold->bcmPtpServoThresholdPhaseLock = _bcm_ptp_uint32_read(resp+i); 475 i += sizeof(uint32); 476 threshold->bcmPtpServoThresholdPhaseUnlock = _bcm_ptp_uint32_read(resp+i); 477 478 return rv; 479 } 480 481 482 /* 483 * Function: 484 * bcm_common_ptp_servo_threshold_set 485 * Purpose: 486 * Set PTP servo threshold properties. 487 * Parameters: 488 * unit - (IN) Unit number. 489 * ptp_id - (IN) PTP stack ID. 490 * clock_num - (IN) PTP clock number. 491 * threshold - (IN) PTP servo threshold properties. 492 * Returns: 493 * BCM_E_XXX - Function status. 494 * Notes: 495 */ 496 int 497 bcm_common_ptp_servo_threshold_set( 498 int unit, 499 bcm_ptp_stack_id_t ptp_id, 500 int clock_num, 501 bcm_ptp_servo_threshold_t *threshold) 502 { 503 int rv = BCM_E_UNAVAIL; 504 505 uint8 payload[PTP_MGMTMSG_PAYLOAD_SERVO_THRESHOLD_SIZE_OCTETS] = {0}; 506 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 507 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 508 int i = 0; 509 510 bcm_ptp_port_identity_t portid; 511 512 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 513 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 514 return rv; 515 } 516 517 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 518 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 519 /* On error, target message to (all clocks, all ports) portIdentity. */ 520 portid = portid_all; 521 } 522 523 /* 524 * Make payload. 525 * Octet 0...5 : Custom management message key/identifier. 526 * Octet 6...9 : Frequency Lock Threshold. 527 * Octet 10...13 : Frequency Unlock Threshold. 528 * Octet 14...17 : Phase Lock Threshold. 529 * Octet 18...21 : Phase Unlock Threshold. 530 */ 531 i = 0; 532 payload[i++] = 'B'; 533 payload[i++] = 'C'; 534 payload[i++] = 'M'; 535 i +=3; 536 _bcm_ptp_uint32_write(payload+i, threshold->bcmPtpServoThresholdFreqLock); 537 i += sizeof(uint32); 538 _bcm_ptp_uint32_write(payload+i, threshold->bcmPtpServoThresholdFreqUnlock); 539 i += sizeof(uint32); 540 _bcm_ptp_uint32_write(payload+i, threshold->bcmPtpServoThresholdPhaseLock); 541 i += sizeof(uint32); 542 _bcm_ptp_uint32_write(payload+i, threshold->bcmPtpServoThresholdPhaseUnlock); 543 544 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, 545 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_SERVO_THRESHOLD, 546 payload, PTP_MGMTMSG_PAYLOAD_SERVO_THRESHOLD_SIZE_OCTETS, 547 resp, &resp_len); 548 549 return rv; 550 } 551 552 /* 553 * Function: 554 * _bcm_ptp_servo_ipdv_configuration_get 555 * Purpose: 556 * Get PTP servo IP packet delay variation (IPDV) configuration properties. 557 * Parameters: 558 * unit - (IN) Unit number. 559 * ptp_id - (IN) PTP stack ID. 560 * clock_num - (IN) PTP clock number. 561 * config - (OUT) PTP servo IPDV configuration properties. 562 * Returns: 563 * BCM_E_XXX - Function status. 564 * Notes: 565 */ 566 int 567 _bcm_ptp_servo_ipdv_configuration_get( 568 int unit, 569 bcm_ptp_stack_id_t ptp_id, 570 int clock_num, 571 _bcm_ptp_ipdv_config_t *config) 572 { 573 int rv = BCM_E_UNAVAIL; 574 575 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 576 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 577 int i = 0; 578 579 bcm_ptp_port_identity_t portid; 580 581 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 582 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 583 return rv; 584 } 585 586 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 587 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 588 /* On error, target message to (all clocks, all ports) portIdentity. */ 589 portid = portid_all; 590 } 591 592 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 593 clock_num, &portid, 594 PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_SERVO_IPDV_CONFIGURATION, 595 0, 0, resp, &resp_len))) { 596 return rv; 597 } 598 599 if (resp_len < PTP_MGMTMSG_PAYLOAD_SERVO_IPDV_CONFIGURATION_SIZE_OCTETS) { 600 /* Internal error : message too short to contain correct data. */ 601 return BCM_E_INTERNAL; 602 } 603 604 /* 605 * Parse response. 606 * Octet 0...5 : Custom management message key/identifier. 607 * BCM<null><null><null>. 608 * Octet 6...7 : IPDV observation interval. 609 * Octet 8...11 : IPDV threshold (nsec). 610 * Octet 12...13 : IPDV pacing factor. 611 */ 612 i = 6; 613 config->observation_interval = _bcm_ptp_uint16_read(resp+i); 614 i += sizeof(uint16); 615 config->threshold = (int32)_bcm_ptp_uint32_read(resp+i); 616 i += sizeof(uint32); 617 config->pacing_factor = _bcm_ptp_uint16_read(resp+i); 618 619 620 return rv; 621 } 622 623 /* 624 * Function: 625 * _bcm_ptp_servo_ipdv_configuration_set 626 * Purpose: 627 * Set PTP servo IP packet delay variation (IPDV) configuration properties. 628 * Parameters: 629 * unit - (IN) Unit number. 630 * ptp_id - (IN) PTP stack ID. 631 * clock_num - (IN) PTP clock number. 632 * config - (IN) PTP servo IPDV configuration properties. 633 * Returns: 634 * BCM_E_XXX - Function status. 635 * Notes: 636 */ 637 int 638 _bcm_ptp_servo_ipdv_configuration_set( 639 int unit, 640 bcm_ptp_stack_id_t ptp_id, 641 int clock_num, 642 const _bcm_ptp_ipdv_config_t config) 643 { 644 int rv = BCM_E_UNAVAIL; 645 646 uint8 payload[PTP_MGMTMSG_PAYLOAD_SERVO_IPDV_CONFIGURATION_SIZE_OCTETS] = {0}; 647 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 648 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 649 int i = 0; 650 651 bcm_ptp_port_identity_t portid; 652 653 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 654 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 655 return rv; 656 } 657 658 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 659 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 660 /* On error, target message to (all clocks, all ports) portIdentity. */ 661 portid = portid_all; 662 } 663 664 /* 665 * Parse response. 666 * Octet 0...5 : Custom management message key/identifier. 667 * BCM<null><null><null>. 668 * Octet 6...7 : IPDV observation interval. 669 * Octet 8...11 : IPDV threshold (nsec). 670 * Octet 12...13 : IPDV pacing factor. 671 */ 672 i = 0; 673 payload[i++] = 'B'; 674 payload[i++] = 'C'; 675 payload[i++] = 'M'; 676 i += 3; 677 _bcm_ptp_uint16_write(payload+i, config.observation_interval); 678 i += sizeof(uint16); 679 _bcm_ptp_uint32_write(payload+i, (uint32)config.threshold); 680 i += sizeof(uint32); 681 _bcm_ptp_uint16_write(payload+i, config.pacing_factor); 682 683 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, 684 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_SERVO_IPDV_CONFIGURATION, 685 payload, PTP_MGMTMSG_PAYLOAD_SERVO_IPDV_CONFIGURATION_SIZE_OCTETS, 686 resp, &resp_len); 687 688 return rv; 689 } 690 691 /* 692 * Function: 693 * _bcm_ptp_servo_performance_get 694 * Purpose: 695 * Get PTP servo performance data / metrics. 696 * Parameters: 697 * unit - (IN) Unit number. 698 * ptp_id - (IN) PTP stack ID. 699 * clock_num - (IN) PTP clock number. 700 * perf - (OUT) PTP servo performance data / metrics. 701 * Returns: 702 * BCM_E_XXX - Function status. 703 * Notes: 704 */ 705 int 706 _bcm_ptp_servo_performance_get( 707 int unit, 708 bcm_ptp_stack_id_t ptp_id, 709 int clock_num, 710 _bcm_ptp_servo_performance_t *perf) 711 { 712 int rv = BCM_E_UNAVAIL; 713 714 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 715 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 716 int i = 0; 717 718 bcm_ptp_port_identity_t portid; 719 720 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 721 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 722 return rv; 723 } 724 725 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 726 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 727 /* On error, target message to (all clocks, all ports) portIdentity. */ 728 portid = portid_all; 729 } 730 731 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 732 clock_num, &portid, 733 PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_SERVO_PERFORMANCE, 734 0, 0, resp, &resp_len))) { 735 return rv; 736 } 737 738 if (resp_len < PTP_MGMTMSG_PAYLOAD_SERVO_PERFORMANCE_SIZE_OCTETS) { 739 /* Internal error : message too short to contain correct data. */ 740 return BCM_E_INTERNAL; 741 } 742 743 /* 744 * Parse response. 745 * Octet 0...5 : Custom management message key/identifier. 746 * BCM<null><null><null>. 747 * Octet 6 : FLL state enumeration. 748 * Octet 7...10 : FLL state duration (sec). 749 * Octet 11...18 : Forward flow weight. 750 * Octet 19...22 : Forward flow transient-free (900 sec window). 751 * Octet 23...26 : Forward flow transient-free (3600 sec window). 752 * Octet 27...34 : Forward flow transactions used (%). 753 * Octet 35...42 : Forward flow operational min TDEV (nsec). 754 * Octet 43...50 : Forward Mafie. 755 * Octet 51...58 : Forward flow min cluster width (nsec). 756 * Octet 59...66 : Forward flow mode width (nsec). 757 * Octet 67...74 : Reverse flow weight. 758 * Octet 75...78 : Reverse flow transient-free (900 sec window). 759 * Octet 79...82 : Reverse flow transient-free (3600 sec window). 760 * Octet 83...90 : Reverse flow transactions used (%). 761 * Octet 91...98 : Reverse flow operational min TDEV (nsec). 762 * Octet 99...106 : Reverse Mafie. 763 * Octet 107...114 : Reverse flow min cluster width (nsec). 764 * Octet 115...122 : Reverse flow mode width (nsec). 765 * Octet 123...130 : Frequency correction (ppb). 766 * Octet 131...138 : Phase correction (ppb). 767 * Octet 139...146 : Output TDEV estimate (nsec). 768 * Octet 147...154 : Output MDEV estimate (ppb). 769 * Octet 155...162 : Residual phase error (nsec). 770 * Octet 163...170 : Minimum round trip delay (nsec). 771 * Octet 171...172 : Sync packet rate (pkts/sec). 772 * Octet 173...174 : Delay packet rate (pkts/sec). 773 * Octet 175...182 : Forward IPDV % below threshold. 774 * Octet 183...190 : Forward maximum IPDV (usec). 775 * Octet 191...198 : Forward interpacket jitter (usec). 776 * Octet 199...206 : Reverse IPDV % below threshold. 777 * Octet 207...214 : Reverse maximum IPDV (usec). 778 * Octet 215...222 : Reverse interpacket jitter (usec). 779 */ 780 i = 6; 781 perf->status.servo_state = (bcm_ptp_servo_state_t)resp[i++]; 782 perf->status.servo_state_dur = _bcm_ptp_uint32_read(resp+i); 783 i += sizeof(uint32); 784 perf->fwd_weight = _bcm_ptp_uint64_read(resp+i); 785 i += sizeof(uint64); 786 perf->fwd_trans_free_900 = _bcm_ptp_uint32_read(resp+i); 787 i += sizeof(uint32); 788 perf->fwd_trans_free_3600 = _bcm_ptp_uint32_read(resp+i); 789 i += sizeof(uint32); 790 perf->fwd_pct = _bcm_ptp_uint64_read(resp+i); 791 i += sizeof(uint64); 792 perf->fwd_min_Tdev = _bcm_ptp_uint64_read(resp+i); 793 i += sizeof(uint64); 794 perf->fwd_Mafie = _bcm_ptp_uint64_read(resp+i); 795 i += sizeof(uint64); 796 perf->fwd_min_cluster_width = _bcm_ptp_uint64_read(resp+i); 797 i += sizeof(uint64); 798 perf->fwd_mode_width = _bcm_ptp_uint64_read(resp+i); 799 i += sizeof(uint64); 800 perf->rev_weight = _bcm_ptp_uint64_read(resp+i); 801 i += sizeof(uint64); 802 perf->rev_trans_free_900 = _bcm_ptp_uint32_read(resp+i); 803 i += sizeof(uint32); 804 perf->rev_trans_free_3600 = _bcm_ptp_uint32_read(resp+i); 805 i += sizeof(uint32); 806 perf->rev_pct = _bcm_ptp_uint64_read(resp+i); 807 i += sizeof(uint64); 808 perf->rev_min_Tdev = _bcm_ptp_uint64_read(resp+i); 809 i += sizeof(uint64); 810 perf->rev_Mafie = _bcm_ptp_uint64_read(resp+i); 811 i += sizeof(uint64); 812 perf->rev_min_cluster_width = _bcm_ptp_uint64_read(resp+i); 813 i += sizeof(uint64); 814 perf->rev_mode_width = _bcm_ptp_uint64_read(resp+i); 815 i += sizeof(uint64); 816 perf->freq_correction = _bcm_ptp_int64_read(resp+i); 817 i += sizeof(uint64); 818 perf->phase_correction = _bcm_ptp_int64_read(resp+i); 819 i += sizeof(uint64); 820 perf->tdev_estimate = _bcm_ptp_uint64_read(resp+i); 821 i += sizeof(uint64); 822 perf->mdev_estimate = _bcm_ptp_uint64_read(resp+i); 823 i += sizeof(uint64); 824 perf->residual_phase_error = _bcm_ptp_int64_read(resp+i); 825 i += sizeof(uint64); 826 perf->min_round_trip_delay = _bcm_ptp_uint64_read(resp+i); 827 i += sizeof(uint64); 828 perf->fwd_pkt_rate = _bcm_ptp_uint16_read(resp+i); 829 i += sizeof(uint16); 830 perf->rev_pkt_rate = _bcm_ptp_uint16_read(resp+i); 831 i += sizeof(uint16); 832 perf->ipdv_data.fwd_pct = _bcm_ptp_uint64_read(resp+i); 833 i += sizeof(uint64); 834 perf->ipdv_data.fwd_max = _bcm_ptp_uint64_read(resp+i); 835 i += sizeof(uint64); 836 perf->ipdv_data.fwd_jitter = _bcm_ptp_uint64_read(resp+i); 837 i += sizeof(uint64); 838 perf->ipdv_data.rev_pct = _bcm_ptp_uint64_read(resp+i); 839 i += sizeof(uint64); 840 perf->ipdv_data.rev_max = _bcm_ptp_uint64_read(resp+i); 841 i += sizeof(uint64); 842 perf->ipdv_data.rev_jitter = _bcm_ptp_uint64_read(resp+i); 843 844 /* Get TDEV/MDEV from CTDEV if not available from the servo: */ 845 if ((COMPILER_64_HI(perf->tdev_estimate) == 0xffffffff) && 846 (COMPILER_64_LO(perf->tdev_estimate) == 0xffffffff)) { 847 /* Get TDEV estimate with tau = 128 */ 848 if (_bcm_ptp_ctdev_get(unit, ptp_id, clock_num, 128, &perf->tdev_estimate) == BCM_E_NONE) { 849 /* Estimate MDEV: TDEV * sqrt(3) / tau ~= TDEV / 74 */ 850 perf->mdev_estimate = _bcm_ptp_llu_div(perf->tdev_estimate, 74); 851 } else { 852 /* No CTDEV data */ 853 COMPILER_64_ZERO(perf->tdev_estimate); 854 COMPILER_64_ZERO(perf->mdev_estimate); 855 } 856 } 857 858 return rv; 859 } 860 861 /* 862 * Function: 863 * _bcm_ptp_servo_ipdv_performance_get 864 * Purpose: 865 * Get PTP servo IP packet delay variation (IPDV) performance data / metrics. 866 * Parameters: 867 * unit - (IN) Unit number. 868 * ptp_id - (IN) PTP stack ID. 869 * clock_num - (IN) PTP clock number. 870 * perf - (OUT) PTP servo IPDV performance data / metrics. 871 * Returns: 872 * BCM_E_XXX - Function status. 873 * Notes: 874 */ 875 int 876 _bcm_ptp_servo_ipdv_performance_get( 877 int unit, 878 bcm_ptp_stack_id_t ptp_id, 879 int clock_num, 880 _bcm_ptp_ipdv_performance_t *perf) 881 { 882 int rv = BCM_E_UNAVAIL; 883 884 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 885 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 886 int i = 0; 887 888 bcm_ptp_port_identity_t portid; 889 890 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 891 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 892 return rv; 893 } 894 895 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 896 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 897 /* On error, target message to (all clocks, all ports) portIdentity. */ 898 portid = portid_all; 899 } 900 901 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 902 clock_num, &portid, 903 PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_SERVO_IPDV_PERFORMANCE, 904 0, 0, resp, &resp_len))) { 905 return rv; 906 } 907 908 if (resp_len < PTP_MGMTMSG_PAYLOAD_SERVO_IPDV_PERFORMANCE_SIZE_OCTETS) { 909 /* Internal error : message too short to contain correct data. */ 910 return BCM_E_INTERNAL; 911 } 912 913 /* 914 * Parse response. 915 * Octet 0...5 : Custom management message key/identifier. 916 * BCM<null><null><null>. 917 * Octet 6...13 : Forward IPDV % below threshold. 918 * Octet 14...21 : Forward maximum IPDV (usec). 919 * Octet 22...29 : Forward interpacket jitter (usec). 920 * Octet 30...37 : Reverse IPDV % below threshold. 921 * Octet 38...45 : Reverse maximum IPDV (usec). 922 * Octet 46...53 : Reverse interpacket jitter (usec). 923 */ 924 i = 6; 925 perf->fwd_pct = _bcm_ptp_uint64_read(resp+i); 926 i += sizeof(uint64); 927 perf->fwd_max = _bcm_ptp_uint64_read(resp+i); 928 i += sizeof(uint64); 929 perf->fwd_jitter = _bcm_ptp_uint64_read(resp+i); 930 i += sizeof(uint64); 931 perf->rev_pct = _bcm_ptp_uint64_read(resp+i); 932 i += sizeof(uint64); 933 perf->rev_max = _bcm_ptp_uint64_read(resp+i); 934 i += sizeof(uint64); 935 perf->rev_jitter = _bcm_ptp_uint64_read(resp+i); 936 937 return rv; 938 } 939 940 /* 941 * Function: 942 * _bcm_ptp_servo_performance_data_clear 943 * Purpose: 944 * Clear (reset) PTP servo performance data / metrics. 945 * Parameters: 946 * unit - (IN) Unit number. 947 * ptp_id - (IN) PTP stack ID. 948 * clock_num - (IN) PTP clock number. 949 * Returns: 950 * BCM_E_XXX - Function status. 951 * Notes: 952 */ 953 int 954 _bcm_ptp_servo_performance_data_clear( 955 int unit, 956 bcm_ptp_stack_id_t ptp_id, 957 int clock_num) 958 { 959 int rv = BCM_E_UNAVAIL; 960 961 uint8 payload[PTP_MGMTMSG_PAYLOAD_MIN_PROPRIETARY_MSG_SIZE_OCTETS] = {0}; 962 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 963 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 964 int i = 0; 965 966 bcm_ptp_port_identity_t portid; 967 968 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 969 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 970 return rv; 971 } 972 973 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 974 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 975 /* On error, target message to (all clocks, all ports) portIdentity. */ 976 portid = portid_all; 977 } 978 979 /* 980 * Make payload. 981 * Octet 0...5 : Custom management message key/identifier. 982 * BCM<null><null><null>. 983 */ 984 i = 0; 985 payload[i++] = 'B'; 986 payload[i++] = 'C'; 987 payload[i++] = 'M'; 988 989 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, 990 &portid, PTP_MGMTMSG_CMD, PTP_MGMTMSG_ID_SERVO_COUNTERS_CLEAR, 991 payload, PTP_MGMTMSG_PAYLOAD_MIN_PROPRIETARY_MSG_SIZE_OCTETS, 992 resp, &resp_len); 993 994 return rv; 995 } 996 997 /* 998 * Function: 999 * bcm_common_ptp_servo_status_get 1000 * Purpose: 1001 * Get PTP servo state and status information. 1002 * Parameters: 1003 * unit - (IN) Unit number. 1004 * ptp_id - (IN) PTP stack ID. 1005 * clock_num - (IN) PTP clock number. 1006 * status - (OUT) PTP servo state and status information. 1007 * Returns: 1008 * BCM_E_XXX - Function status. 1009 * Notes: 1010 */ 1011 int 1012 bcm_common_ptp_servo_status_get( 1013 int unit, 1014 bcm_ptp_stack_id_t ptp_id, 1015 int clock_num, 1016 bcm_ptp_servo_status_t *status) 1017 { 1018 int rv = BCM_E_UNAVAIL; 1019 1020 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1021 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1022 int i = 0; 1023 1024 bcm_ptp_port_identity_t portid; 1025 1026 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 1027 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1028 return rv; 1029 } 1030 1031 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 1032 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 1033 /* On error, target message to (all clocks, all ports) portIdentity. */ 1034 portid = portid_all; 1035 } 1036 1037 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 1038 clock_num, &portid, 1039 PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_SERVO_STATUS, 1040 0, 0, resp, &resp_len))) { 1041 return rv; 1042 } 1043 1044 if (resp_len < PTP_MGMTMSG_PAYLOAD_SERVO_STATUS_SIZE_OCTETS) { 1045 /* Internal error : message too short to contain correct data. */ 1046 return BCM_E_INTERNAL; 1047 } 1048 1049 /* 1050 * Parse response. 1051 * Octet 0...5 : Custom management message key/identifier. 1052 * BCM<null><null><null>. 1053 * Octet 6 : FLL state enumeration. 1054 * Octet 7...10 : FLL state duration (sec). 1055 * Octet 11...14 : Locked Status enumeration. 1056 */ 1057 i = 6; 1058 1059 status->servo_state = (bcm_ptp_servo_state_t)resp[i++]; 1060 status->servo_state_dur = _bcm_ptp_uint32_read(resp+i); 1061 i += 4; 1062 status->lock_status = (bcm_ptp_servo_lock_status_t)resp[i]; 1063 1064 1065 return rv; 1066 } 1067 1068 /* 1069 * Function: 1070 * _bcm_ptp_servo_state_set 1071 * Purpose: 1072 * set PTP servo state and status information. 1073 * Parameters: 1074 * unit - (IN) Unit number. 1075 * ptp_id - (IN) PTP stack ID. 1076 * clock_num - (IN) PTP clock number. 1077 * state - (IN) PTP ext-servo's state. 1078 * Returns: 1079 * BCM_E_XXX - Function status. 1080 * Notes: 1081 */ 1082 int 1083 _bcm_ptp_servo_state_set( 1084 int unit, 1085 bcm_ptp_stack_id_t ptp_id, 1086 int clock_num, 1087 int servo_state) 1088 { 1089 int rv = BCM_E_UNAVAIL; 1090 1091 uint8 payload[32] = {0}; 1092 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1093 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1094 int i = 0; 1095 1096 bcm_ptp_port_identity_t portid; 1097 1098 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 1099 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1100 return rv; 1101 } 1102 1103 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 1104 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 1105 /* On error, target message to (all clocks, all ports) portIdentity. */ 1106 portid = portid_all; 1107 } 1108 1109 i = 0; 1110 payload[i++] = 'B'; 1111 payload[i++] = 'C'; 1112 payload[i++] = 'M'; 1113 payload[i++] = '\0'; 1114 payload[i++] = '\0'; 1115 payload[i++] = '\0'; 1116 1117 _bcm_ptp_uint32_write(payload + i, servo_state); 1118 i += 4; 1119 1120 rv = _bcm_ptp_management_message_send(unit, ptp_id, 1121 clock_num, &portid, 1122 PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_SERVO_STATUS, 1123 payload, i, 1124 resp, &resp_len); 1125 1126 return rv; 1127 } 1128 1129 /* 1130 * Function: 1131 * bcm_common_ptp_phase_offset_set 1132 * Purpose: 1133 * Set phase offsets for path asymmetry compensation 1134 * Parameters: 1135 * unit - Unit number 1136 * ptp_id - PTP stack ID 1137 * clock_num - PTP clock number 1138 * *offset - PTP servo phase holdover state offsets 1139 * Returns: 1140 * int 1141 * Notes: 1142 */ 1143 1144 int 1145 bcm_common_ptp_phase_offset_set( 1146 int unit, 1147 bcm_ptp_stack_id_t ptp_id, 1148 int clock_num, 1149 const bcm_ptp_phase_offset_t *offset) 1150 { 1151 int rc; 1152 bcm_ptp_phase_holdover_state_t state; 1153 state.phase_slew_rate_ppb = offset->phase_slew_rate_ppb; 1154 state.sync_phase_offset_ns = offset->sync_phase_offset_ns; 1155 state.reported_phase_offset = offset->reported_phase_offset; 1156 state.delta_phase_offset = offset->delta_phase_offset; 1157 state.fixed_phase_offset = offset->fixed_phase_offset; 1158 state.use_fixed_phase_offset = offset->use_fixed_phase_offset; 1159 1160 rc = _bcm_ptp_phase_holdover_set(unit, ptp_id, clock_num, &state); 1161 1162 return (rc); 1163 } 1164 1165 /* 1166 * Function: 1167 * bcm_common_ptp_phase_offset_get 1168 * Purpose: 1169 * Get phase offsets for path asymmetry compensation 1170 * Parameters: 1171 * unit - Unit number 1172 * ptp_id - PTP stack ID 1173 * clock_num - PTP clock number 1174 * *offset - PTP servo phase holdover state offsets 1175 * Returns: 1176 * int 1177 * Notes: 1178 */ 1179 1180 int 1181 bcm_common_ptp_phase_offset_get( 1182 int unit, 1183 bcm_ptp_stack_id_t ptp_id, 1184 int clock_num, 1185 bcm_ptp_phase_offset_t *offset) 1186 { 1187 int rc; 1188 bcm_ptp_phase_holdover_state_t state; 1189 1190 1191 rc = _bcm_ptp_phase_holdover_get(unit, ptp_id, clock_num, &state); 1192 1193 offset->reported_phase_offset = state.reported_phase_offset; 1194 offset->delta_phase_offset = state.delta_phase_offset; 1195 offset->fixed_phase_offset = state.fixed_phase_offset; 1196 offset->use_fixed_phase_offset = state.use_fixed_phase_offset; 1197 offset->phase_slew_rate_ppb = state.phase_slew_rate_ppb; 1198 offset->sync_phase_offset_ns = state.sync_phase_offset_ns; 1199 1200 return (rc); 1201 } 1202 1203 1204 /* 1205 * Function: 1206 * _bcm_ptp_servo_phase_offset_get 1207 * Purpose: 1208 * Get phase offsets for external servo 1209 * Parameters: 1210 * unit - (IN) Unit number. 1211 * ptp_id - (IN) PTP stack ID. 1212 * clock_num - (IN) PTP clock number. 1213 * state - (OUT) PTP servo phase holdover state 1214 * Returns: 1215 * BCM_E_XXX - Function status. 1216 * Notes: 1217 */ 1218 int 1219 _bcm_ptp_servo_phase_offset_get( 1220 int unit, 1221 bcm_ptp_stack_id_t ptp_id, 1222 int clock_num, 1223 int64 *phase_offset) 1224 { 1225 int rv; 1226 int i; 1227 1228 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1229 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1230 1231 bcm_ptp_port_identity_t portid; 1232 1233 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 1234 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1235 return rv; 1236 } 1237 1238 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 1239 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 1240 /* On error, target message to (all clocks, all ports) portIdentity. */ 1241 portid = portid_all; 1242 } 1243 1244 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 1245 clock_num, &portid, 1246 PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_SERVO_PHASE_OFFSET, 1247 0, 0, resp, &resp_len))) { 1248 return rv; 1249 } 1250 1251 /* 1252 * Parse response. 1253 * Octet 0...5 : Custom management message key/identifier. 1254 * BCM<null><null><null>. 1255 * Octet 6...13 : Reported phase offset. 1256 */ 1257 i = 6; 1258 *phase_offset = _bcm_ptp_int64_read(resp + i); 1259 i += 8; 1260 1261 return BCM_E_NONE; 1262 } 1263 1264 /* 1265 * Function: _bcm_ptp_servo_phase_offset_set 1266 * 1267 * Purpose: 1268 * Set phase offsets for path asymmetry compensation. 1269 * Parameters: 1270 * unit - (IN) Unit number. 1271 * ptp_id - (IN) PTP stack ID. 1272 * clock_num - (IN) PTP clock number. 1273 * state - (IN) PTP servo phase holdover state 1274 * Returns: 1275 * BCM_E_XXX - Function status. 1276 * Notes: 1277 */ 1278 #ifndef __KERNEL__ 1279 int 1280 _bcm_ptp_servo_phase_offset_set( 1281 int unit, 1282 bcm_ptp_stack_id_t ptp_id, 1283 int clock_num, 1284 const double *phase_offset) 1285 #else 1286 int 1287 _bcm_ptp_servo_phase_offset_set( 1288 int unit, 1289 bcm_ptp_stack_id_t ptp_id, 1290 int clock_num, 1291 const int64 *phase_offset) 1292 #endif /* __KERNEL__ */ 1293 { 1294 int rv; 1295 int i; 1296 int64 phase_off; 1297 1298 uint8 payload[PTP_MGMTMSG_PAYLOAD_PHASE_OFFSET_SIZE_OCTETS] = {0}; 1299 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1300 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1301 1302 bcm_ptp_port_identity_t portid; 1303 1304 if(g_apts_enabled && 1305 (g_apts_current_op_mode != bcmPtpClockAptsModeSyncEHoldover) && 1306 (g_apts_current_op_mode != bcmPtpClockAptsModeHoldoverHoldover)){ 1307 /* Do not apply phase corrections from servo */ 1308 rv = BCM_E_NONE; 1309 return rv; 1310 } 1311 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 1312 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1313 return rv; 1314 } 1315 1316 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 1317 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 1318 /* On error, target message to (all clocks, all ports) portIdentity. */ 1319 portid = portid_all; 1320 } 1321 1322 phase_off = *phase_offset; 1323 1324 #ifndef __KERNEL__ 1325 LOG_INFO(BSL_LS_BCM_PTP, 1326 (BSL_META_U(unit, "servo phase offset set[%lf] phase_off[%lld: %llx]\n"), 1327 (double)*phase_offset, (long long int)phase_off, (long long unsigned int)phase_off)); 1328 #else 1329 LOG_INFO(BSL_LS_BCM_PTP, 1330 (BSL_META_U(unit, "servo phase offset phase_off[%lld: %llx]\n"), 1331 (long long int)phase_off, (long long unsigned int)phase_off)); 1332 #endif /* __KERNEL__ */ 1333 /* 1334 * Make payload. 1335 * Octet 0...5 : Custom management message key/identifier. 1336 * BCM<null><null><null>. 1337 * Octet 6...13 : phase offset. 1338 */ 1339 i = 0; 1340 payload[i++] = 'B'; 1341 payload[i++] = 'C'; 1342 payload[i++] = 'M'; 1343 payload[i++] = '\0'; 1344 payload[i++] = '\0'; 1345 payload[i++] = '\0'; 1346 1347 _bcm_ptp_int64_write(payload + i, phase_off); 1348 i += 8; 1349 1350 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 1351 clock_num, &portid, 1352 PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_SERVO_PHASE_OFFSET, 1353 payload, PTP_MGMTMSG_PAYLOAD_SERVO_PHASE_OFFSET_SIZE_OCTETS, 1354 resp, &resp_len))) { 1355 return rv; 1356 } 1357 1358 return BCM_E_NONE; 1359 } 1360 1361 /* 1362 * Function: 1363 * _bcm_ptp_phase_holdover_get 1364 * Purpose: 1365 * Get phase offsets for path asymmetry compensation. 1366 * Parameters: 1367 * unit - (IN) Unit number. 1368 * ptp_id - (IN) PTP stack ID. 1369 * clock_num - (IN) PTP clock number. 1370 * state - (OUT) PTP servo phase holdover state 1371 * Returns: 1372 * BCM_E_XXX - Function status. 1373 * Notes: 1374 */ 1375 int 1376 _bcm_ptp_phase_holdover_get( 1377 int unit, 1378 bcm_ptp_stack_id_t ptp_id, 1379 int clock_num, 1380 bcm_ptp_phase_holdover_state_t *state) 1381 { 1382 int rv; 1383 int i; 1384 1385 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1386 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1387 1388 bcm_ptp_port_identity_t portid; 1389 1390 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 1391 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1392 return rv; 1393 } 1394 1395 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 1396 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 1397 /* On error, target message to (all clocks, all ports) portIdentity. */ 1398 portid = portid_all; 1399 } 1400 1401 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 1402 clock_num, &portid, 1403 PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_PHASE_OFFSET, 1404 0, 0, resp, &resp_len))) { 1405 return rv; 1406 } 1407 1408 /* 1409 * Parse response. 1410 * Octet 0...5 : Custom management message key/identifier. 1411 * BCM<null><null><null>. 1412 * Octet 6...13 : Reported phase offset. 1413 * Octet 14...21 : Delta offset. 1414 * Octet 22...29 : Fixed phase offset. 1415 * Octet 30...33 : Use fixed phase offset flag. 1416 * Octet 34...37 : Phase slew rate - maximum phase offset correction rate. 1417 * Octet 38...41 : Sync phase offst - maximum phase offset correction 1418 * via rate-limited phase slew. 1419 */ 1420 i = 6; 1421 state->reported_phase_offset = _bcm_ptp_int64_read(resp + i); 1422 i += 8; 1423 state->delta_phase_offset = _bcm_ptp_int64_read(resp + i); 1424 i += 8; 1425 state->fixed_phase_offset = _bcm_ptp_int64_read(resp + i); 1426 i += 8; 1427 state->use_fixed_phase_offset = _bcm_ptp_uint32_read(resp + i); 1428 i += 4; 1429 state->phase_slew_rate_ppb = _bcm_ptp_uint32_read(resp + i); 1430 i += 4; 1431 state->sync_phase_offset_ns = _bcm_ptp_uint32_read(resp + i); 1432 1433 return BCM_E_NONE; 1434 } 1435 1436 /* 1437 * Function: 1438 * _bcm_ptp_phase_holdover_set 1439 * Purpose: 1440 * Set phase offsets for path asymmetry compensation. 1441 * Parameters: 1442 * unit - (IN) Unit number. 1443 * ptp_id - (IN) PTP stack ID. 1444 * clock_num - (IN) PTP clock number. 1445 * state - (IN) PTP servo phase holdover state 1446 * Returns: 1447 * BCM_E_XXX - Function status. 1448 * Notes: 1449 */ 1450 int 1451 _bcm_ptp_phase_holdover_set( 1452 int unit, 1453 bcm_ptp_stack_id_t ptp_id, 1454 int clock_num, 1455 const bcm_ptp_phase_holdover_state_t *state) 1456 { 1457 int rv; 1458 int i; 1459 1460 uint8 payload[PTP_MGMTMSG_PAYLOAD_PHASE_OFFSET_SIZE_OCTETS] = {0}; 1461 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1462 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1463 1464 bcm_ptp_port_identity_t portid; 1465 1466 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 1467 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1468 return rv; 1469 } 1470 1471 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 1472 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 1473 /* On error, target message to (all clocks, all ports) portIdentity. */ 1474 portid = portid_all; 1475 } 1476 1477 /* 1478 * Make payload. 1479 * Octet 0...5 : Custom management message key/identifier. 1480 * BCM<null><null><null>. 1481 * Octet 6...13 : Delta offset. 1482 * Octet 14...21 : Fixed phase offset. 1483 * Octet 22...25 : Use fixed phase offset flag. 1484 * Octet 26...29 : Phase slew rate - maximum phase offset correction rate. 1485 * Octet 30...33 : Sync phase offst - maximum phase offset correction 1486 * via rate-limited phase slew. 1487 */ 1488 i = 0; 1489 payload[i++] = 'B'; 1490 payload[i++] = 'C'; 1491 payload[i++] = 'M'; 1492 payload[i++] = '\0'; 1493 payload[i++] = '\0'; 1494 payload[i++] = '\0'; 1495 1496 _bcm_ptp_int64_write(payload + i, state->delta_phase_offset); 1497 i += 8; 1498 _bcm_ptp_int64_write(payload + i, state->fixed_phase_offset); 1499 i += 8; 1500 if (state->use_fixed_phase_offset) { 1501 _bcm_ptp_uint32_write(payload + i, 1); 1502 } else { 1503 _bcm_ptp_uint32_write(payload + i, 0); 1504 } 1505 i += 4; 1506 _bcm_ptp_uint32_write(payload + i, state->phase_slew_rate_ppb); 1507 i += 4; 1508 _bcm_ptp_uint32_write(payload + i, state->sync_phase_offset_ns); 1509 1510 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 1511 clock_num, &portid, 1512 PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_PHASE_OFFSET, 1513 payload, PTP_MGMTMSG_PAYLOAD_PHASE_OFFSET_SIZE_OCTETS, 1514 resp, &resp_len))) { 1515 return rv; 1516 } 1517 1518 return BCM_E_NONE; 1519 } 1520 1521 /* 1522 * Function: 1523 * _bcm_ptp_freq_corr_get 1524 * Purpose: 1525 * Gets current frequency offsets 1526 * Parameters: 1527 * unit - (IN) Unit number. 1528 * ptp_id - (IN) PTP stack ID. 1529 * clock_num - (IN) PTP clock number. 1530 * freq_corr_ppt - (IN) Servo-issued frequency correction 1531 * offset_freq_ppt - (IN) User-specified frequency offset 1532 * Returns: 1533 * BCM_E_XXX - Function status. 1534 * Notes: 1535 * The current frequency offset is (freq_corr_ppt + offset_freq_ppt) 1536 */ 1537 int 1538 _bcm_ptp_freq_corr_get( 1539 int unit, 1540 bcm_ptp_stack_id_t ptp_id, 1541 int clock_num, 1542 int32 *freq_corr_ppt, 1543 int32 *offset_freq_ppt) 1544 { 1545 int rv; 1546 1547 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1548 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1549 uint8 *curs; 1550 1551 bcm_ptp_port_identity_t portid; 1552 1553 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 1554 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1555 return rv; 1556 } 1557 1558 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 1559 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 1560 /* On error, target message to (all clocks, all ports) portIdentity. */ 1561 portid = portid_all; 1562 } 1563 1564 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 1565 clock_num, &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_FREQUENCY, 1566 0, 0, resp, &resp_len))) { 1567 return rv; 1568 } 1569 1570 /* 1571 * Parse response. 1572 * Octet 0...5 : Custom management message key/identifier. 1573 * BCM<null><null><null>. 1574 * Octet 6...9 : Frequency Correction in PPT (* 1e-12) 1575 * Octet 10...13 : Frequency Offset from Servo's correction in PPT 1576 */ 1577 if (resp_len < 6 + 4 + 4) { 1578 return BCM_E_FAIL; 1579 } 1580 1581 curs = resp + 6; /* after BCM\0\0\0 */ 1582 *freq_corr_ppt = _bcm_ptp_uint32_read(curs); curs += 4; 1583 *offset_freq_ppt = _bcm_ptp_uint32_read(curs); curs += 4; 1584 1585 return BCM_E_NONE; 1586 } 1587 1588 1589 /* 1590 * Function: 1591 * _bcm_ptp_freq_corr_set 1592 * Purpose: 1593 * Gets current frequency offsets 1594 * Parameters: 1595 * unit - (IN) Unit number. 1596 * ptp_id - (IN) PTP stack ID. 1597 * clock_num - (IN) PTP clock number. 1598 * freq_corr_ppt - (IN) Servo-issued frequency correction 1599 * offset_freq_ppt - (IN) User-specified frequency offset 1600 * Returns: 1601 * BCM_E_XXX - Function status. 1602 * Notes: 1603 * The current frequency offset is (freq_corr_ppt + offset_freq_ppt) 1604 * If the servo is updating its frequency correction estimate, the 1605 * user-supplied 'freq_corr_ppt' value will be overwritten with that 1606 * new estimate. 1607 */ 1608 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 1609 int 1610 _bcm_ptp_freq_corr_set( 1611 int unit, 1612 bcm_ptp_stack_id_t ptp_id, 1613 int clock_num, 1614 double freq_corr_ppb, 1615 double freq_offset_ppb) 1616 #else 1617 int 1618 _bcm_ptp_freq_corr_set( 1619 int unit, 1620 bcm_ptp_stack_id_t ptp_id, 1621 int clock_num, 1622 int32 freq_corr_ppt, 1623 int32 freq_offset_ppt) 1624 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */ 1625 { 1626 int rv; 1627 int i; 1628 1629 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 1630 int32 freq_corr_ppt; 1631 int32 freq_offset_ppt; 1632 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */ 1633 1634 uint8 payload[PTP_MGMTMSG_PAYLOAD_PHASE_OFFSET_SIZE_OCTETS] = {0}; 1635 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1636 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1637 1638 bcm_ptp_port_identity_t portid; 1639 1640 if (g_apts_enabled && 1641 (g_apts_current_op_mode != bcmPtpClockAptsModeGpsGps) && 1642 (g_apts_current_op_mode != bcmPtpClockAptsModePtpPtp)){ 1643 /* Do not apply frequency corrections from servo */ 1644 rv = BCM_E_NONE; 1645 return rv; 1646 } 1647 1648 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 1649 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1650 return rv; 1651 } 1652 1653 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 1654 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 1655 /* On error, target message to (all clocks, all ports) portIdentity. */ 1656 portid = portid_all; 1657 } 1658 1659 /* 1660 * Make payload. 1661 * Octet 0...5 : Custom management message key/identifier. 1662 * BCM<null><null><null>. 1663 * Octet 6...9 : Frequency Correction in PPT (* 1e-12) 1664 * Octet 10...13 : Frequency Offset from Servo's correction in PPT 1665 */ 1666 i = 0; 1667 payload[i++] = 'B'; 1668 payload[i++] = 'C'; 1669 payload[i++] = 'M'; 1670 payload[i++] = '\0'; 1671 payload[i++] = '\0'; 1672 payload[i++] = '\0'; 1673 1674 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 1675 freq_corr_ppt = (freq_corr_ppb * 1000); 1676 freq_offset_ppt = (freq_offset_ppb * 1000); 1677 1678 LOG_INFO(BSL_LS_BCM_PTP, 1679 (BSL_META_U(unit, " freq corr set: freq_correction_ppb[%lf : 0x%016llx] freq_corr_offset_ppb[%lf : %llx]\n"), 1680 freq_corr_ppb, (unsigned long long int)freq_corr_ppb, freq_offset_ppb, (unsigned long long int)freq_offset_ppb)); 1681 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */ 1682 1683 _bcm_ptp_uint32_write(payload + i, freq_corr_ppt); i += 4; 1684 _bcm_ptp_uint32_write(payload + i, freq_offset_ppt); i += 4; 1685 1686 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 1687 clock_num, &portid, 1688 PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_FREQUENCY, 1689 payload, PTP_MGMTMSG_PAYLOAD_FREQUENCY_SIZE_OCTETS, 1690 resp, &resp_len))) { 1691 return rv; 1692 } 1693 1694 return BCM_E_NONE; 1695 } 1696 1697 /* 1698 * Function: 1699 * _bcm_ptp_servo_type_get 1700 * Purpose: 1701 * Derive the servo type based on the provided profile 1702 * Parameters: 1703 * profile_type - (IN) clock profile: 8265.1, 8275.1, def-1588 etc. 1704 * servo - (OUT) Servo type [bcm||other] for the provided 1705 * clock profile 1706 * Returns: 1707 * BCM_E_XXX - Function status. 1708 * Notes: 1709 * Add new profiles to the list as they are introduced in future 1710 * update the servo types as introduced in future 1711 */ 1712 int 1713 _bcm_ptp_servo_type_get (uint32 profile_type, uint32 *servo) 1714 { 1715 int rv = BCM_E_NONE; 1716 1717 switch (profile_type) { 1718 case e_PtpProfType_8265p1: 1719 case e_PtpProfType_8275p2: 1720 *servo = bcmPTPServoTypeExt; 1721 break; 1722 1723 case e_PtpProfType_8275p1: 1724 /*case e_PtpProfType_8273p2:*/ 1725 *servo = bcmPTPServoTypeBCM; 1726 break; 1727 1728 default: 1729 rv = BCM_E_UNAVAIL;; 1730 } 1731 return rv ; 1732 } 1733 1734 /* 1735 * Function: 1736 * _bcm_ptp_servo_synce_freq_corr_get_in_combined_mode 1737 * Purpose: 1738 * Get the brcm servo's freq correction in TS0/TS1 combined mode 1739 * Parameters: 1740 * Returns: 1741 * BCM_E_XXX - Function status. 1742 * Notes: 1743 */ 1744 int 1745 _bcm_ptp_bcm_servo_synce_freq_corr_get_in_combined_mode(int unit, int stack_id, int64 *servo_freq_correction_pbb) 1746 { 1747 int rv = BCM_E_NONE; 1748 1749 _bcm_ptp_stack_info_t *stack_p; 1750 _bcm_ptp_info_t *ptp_info_p; 1751 _bcm_ptp_servo_performance_t perf; 1752 bcm_ptp_clock_info_t clock_info; 1753 uint32 profile_type; 1754 uint32 servo = 0; 1755 1756 SET_PTP_INFO; 1757 stack_p = &ptp_info_p->stack_info[stack_id]; 1758 1759 if (!(stack_p->flags & BCM_PTP_STACK_TIMESTAMPER_COMBINED_MODE)) 1760 { 1761 return BCM_E_UNAVAIL; 1762 } 1763 1764 if(BCM_FAILURE(bcm_ptp_clock_get(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, &clock_info))) { 1765 return rv; 1766 } 1767 profile_type = ((clock_info.flags >> 8) & 0x0F); 1768 _bcm_ptp_servo_type_get(profile_type, &servo); 1769 1770 if (servo != bcmPTPServoTypeBCM) { 1771 return BCM_E_UNAVAIL; 1772 } 1773 1774 if(BCM_FAILURE(_bcm_ptp_servo_performance_get(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, &perf))) { 1775 return BCM_E_UNAVAIL; 1776 } 1777 *servo_freq_correction_pbb = perf.freq_correction/(int64)PTP_SERVO_FREQ_CORRECTION_FIXEDPOINT_SCALEFACTOR; 1778 1779 return rv ; 1780 } 1781 1782 1783 #endif /* defined(INCLUDE_PTP)*/