timesource.c (52080B)
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: timesource.c 8 * 9 * Purpose: 10 * 11 * Functions: 12 * bcm_common_ptp_tod_input_sources_set 13 * bcm_common_ptp_tod_input_sources_get 14 * bcm_common_ptp_tod_output_set 15 * bcm_common_ptp_tod_output_remove 16 * bcm_common_ptp_tod_output_get 17 * bcm_common_ptp_timesource_input_status_get 18 * bcm_common_ptp_input_channel_precedence_mode_set 19 * bcm_common_ptp_input_channel_switching_mode_set 20 * bcm_common_ptp_input_channels_get 21 * bcm_common_ptp_input_channels_set 22 * bcm_common_ptp_synce_output_set 23 * bcm_common_ptp_synce_output_get 24 * bcm_common_ptp_signal_output_get 25 * bcm_common_ptp_signal_output_remove 26 * bcm_common_ptp_signal_output_set 27 * bcm_common_ptp_sync_phy 28 */ 29 30 #if defined(INCLUDE_PTP) 31 32 #include <shared/bsl.h> 33 34 #include <soc/defs.h> 35 #include <soc/drv.h> 36 37 #include <sal/core/dpc.h> 38 39 #include <bcm/ptp.h> 40 #include <bcm_int/common/ptp.h> 41 #include <bcm_int/ptp_common.h> 42 #include <bcm/error.h> 43 44 #include <shared/bsl.h> 45 #include <bcm_int/common/PTP_feature.h> 46 47 /* Constants and variables. */ 48 #define PTP_TIMESOURCE_USE_MANAGEMENT_MSG (1) 49 #define PTP_TIMESOURCE_SIGNAL_OUTPUT_DATA_SIZE_OCTETS (17) 50 51 52 static const bcm_ptp_port_identity_t portid_all = 53 {{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, PTP_IEEE1588_ALL_PORTS}; 54 55 /* 56 * Function: 57 * _bcm_common_ptp_configure_serial_tod 58 * Purpose: 59 * Configure TOD for serial output. 60 * Parameters: 61 * unit - (IN) Unit number. 62 * ptp_id - (IN) PTP stack ID. 63 * clock_num - (IN) PTP clock number. 64 * uart_num - (IN) UART number. 65 * offset - (IN) ToD offset (nsec). 66 * delay - (IN) ToD delay (nsec). 67 * fw_format_type - (IN) ToD format type selector (per firmware definition) 68 * format_str_len - (IN) ToD format string length. 69 * format_str - (IN) ToD format string. 70 * Returns: 71 * BCM_E_XXX - Function status. 72 * Notes: 73 */ 74 int 75 _bcm_common_ptp_configure_serial_tod( 76 int unit, 77 bcm_ptp_stack_id_t ptp_id, 78 int clock_num, 79 int uart_num, 80 int32 offset_sec, 81 int32 offset_ns, 82 uint32 delay, 83 int fw_format_type, 84 int format_str_len, 85 const char *format_str, 86 uint8 l2_header_length, 87 const uint8 l2_header[BCM_PTP_MAX_L2_HEADER_LENGTH], 88 uint32 tod_baud_rate) 89 { 90 int rv = BCM_E_UNAVAIL; 91 92 bcm_ptp_port_identity_t portid; 93 uint8 payload[PTP_MGMTMSG_PAYLOAD_CONFIGURE_TOD_OUT_SIZE_OCTETS] = {0}; 94 uint8 *curs = &payload[0]; 95 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 96 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 97 int copy_len; 98 99 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 100 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 101 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 102 return rv; 103 } 104 105 /* LOG_CLI((BSL_META_U(unit, 106 "configure_serial_tod() uart_num:%d\n"), uart_num)); */ 107 108 /* Make payload. */ 109 sal_memcpy(curs, "BCM\0\0\0", 6); curs += 6; 110 *curs++ = uart_num; 111 _bcm_ptp_uint32_write(curs, (uint32)offset_sec); curs += sizeof(uint32); 112 _bcm_ptp_uint32_write(curs, (uint32)offset_ns); curs += sizeof(uint32); 113 _bcm_ptp_uint32_write(curs, delay); curs += sizeof(uint32); 114 *curs++ = fw_format_type; 115 116 copy_len = format_str_len; 117 if (copy_len > BCM_PTP_MAX_TOD_FORMAT_STRING) { 118 copy_len = BCM_PTP_MAX_TOD_FORMAT_STRING; 119 } else if (copy_len < 0) { 120 copy_len = 0; 121 } 122 *curs++ = copy_len; 123 124 if (format_str) { 125 sal_memcpy(curs, format_str, copy_len); 126 } 127 curs += BCM_PTP_MAX_TOD_FORMAT_STRING; 128 129 sal_memset(curs, 0, 18); 130 if (l2_header_length <= 18) { 131 if (l2_header) { 132 sal_memcpy(curs, l2_header, l2_header_length); 133 } 134 } else { 135 LOG_ERROR(BSL_LS_BCM_COMMON, 136 (BSL_META_U(unit, 137 "Invalid L2 length (must be <= 18)"))); 138 return BCM_E_PARAM; 139 } 140 141 curs += 18; 142 143 _bcm_ptp_uint32_write(curs, tod_baud_rate); 144 curs += sizeof(uint32); 145 146 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 147 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 148 /* On error, target message to (all clocks, all ports) portIdentity. */ 149 portid = portid_all; 150 } 151 152 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, &portid, 153 PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_CONFIGURE_TOD_OUT, 154 payload, curs - payload, resp, &resp_len); 155 156 return rv; 157 } 158 159 /* 160 * Function: 161 * bcm_common_ptp_tod_input_sources_set 162 * Purpose: 163 * Set PTP TOD input(s). 164 * Parameters: 165 * unit - (IN) Unit number. 166 * ptp_id - (IN) PTP stack ID. 167 * clock_num - (IN) PTP clock number. 168 * num_tod_sources - (IN) Number of ToD inputs. 169 * tod_sources - (IN) PTP ToD input configuration. 170 * Returns: 171 * BCM_E_XXX - Function status. 172 * Notes: 173 */ 174 int 175 bcm_common_ptp_tod_input_sources_set( 176 int unit, 177 bcm_ptp_stack_id_t ptp_id, 178 int clock_num, 179 int num_tod_sources, 180 bcm_ptp_tod_input_t *tod_sources) 181 { 182 int rv = BCM_E_UNAVAIL; 183 184 bcm_ptp_port_identity_t portid; 185 uint8 payload[PTP_MGMTMSG_PAYLOAD_CONFIGURE_TOD_IN_SIZE_OCTETS*2] = {0}; 186 uint8 *curs = &payload[0]; 187 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 188 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 189 190 int fw_format_type = 0; 191 uint8 *format_str = 0; 192 uint8 *mask_str = 0; 193 194 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 195 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 196 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 197 return rv; 198 } 199 200 201 202 switch (num_tod_sources) { 203 case 0: 204 /* already have values set to have no TOD in */ 205 break; 206 case 1: 207 fw_format_type = tod_sources[0].format + 1; /* ordering must be same on fw side */ 208 format_str = tod_sources[0].format_str; 209 mask_str = tod_sources[0].mask_str; 210 break; 211 default: 212 /* only currently support a single TOD-in */ 213 return BCM_E_PARAM; 214 } 215 216 /* Make payload. */ 217 sal_memcpy(curs, "BCM\0\0\0", 6); curs += 6; 218 *curs++ = tod_sources[0].source; 219 _bcm_ptp_uint32_write(curs, (uint32)tod_sources[0].tod_offset_sec); curs += 4; 220 _bcm_ptp_uint32_write(curs, (uint32)tod_sources[0].tod_offset_ns); curs += 4; 221 *curs++ = fw_format_type; 222 223 *curs++ = (format_str) ? strlen((char*)format_str) : 0; 224 225 if (format_str) { 226 sal_memcpy(curs, format_str, PTP_TIMESOURCE_TODIN_MGMTMSG_FORMAT_LENGTH); 227 } 228 curs += PTP_TIMESOURCE_TODIN_MGMTMSG_FORMAT_LENGTH; 229 230 *curs++ = (mask_str) ? strlen((char*)mask_str) : 0; 231 232 if (mask_str) { 233 sal_memcpy(curs, mask_str, PTP_TIMESOURCE_TODIN_MGMTMSG_MASK_LENGTH); 234 } 235 curs += PTP_TIMESOURCE_TODIN_MGMTMSG_MASK_LENGTH; 236 237 if (tod_sources[0].peer_address.raw_l2_header_length == 18) { 238 sal_memcpy(curs, tod_sources[0].peer_address.raw_l2_header + 6, 6); /* pick out src MAC */ 239 curs += 6; 240 sal_memcpy(curs, tod_sources[0].peer_address.raw_l2_header + 14, 2); /* pick out VLAN */ 241 curs += 2; 242 sal_memcpy(curs, tod_sources[0].peer_address.raw_l2_header + 16, 2); /* pick out EtherType */ 243 curs += 2; 244 } else { 245 curs += 6 + 2 + 2; 246 } 247 248 _bcm_ptp_uint32_write(curs, (uint32)tod_sources[0].tod_baud_rate); curs += 4; 249 250 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 251 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 252 /* On error, target message to (all clocks, all ports) portIdentity. */ 253 portid = portid_all; 254 } 255 256 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, 257 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_CONFIGURE_TOD_IN, 258 payload, curs - payload, resp, &resp_len))) { 259 return rv; 260 } 261 262 if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_tod_input_set(unit, ptp_id, clock_num, 263 num_tod_sources - 1, tod_sources))) { 264 return rv; 265 } 266 267 return BCM_E_NONE; 268 } 269 270 /* 271 * Function: 272 * bcm_common_ptp_tod_input_sources_get 273 * Purpose: 274 * Get PTP ToD input source(s). 275 * Parameters: 276 * unit - (IN) Unit number. 277 * ptp_id - (IN) PTP stack ID. 278 * clock_num - (IN) PTP clock number. 279 * num_tod_sources - (IN/OUT) Number of ToD inputs. (max on input) 280 * tod_sources - (OUT) Array of ToD inputs. 281 * Returns: 282 * BCM_E_XXX - Function status. 283 * Notes: 284 */ 285 int 286 bcm_common_ptp_tod_input_sources_get( 287 int unit, 288 bcm_ptp_stack_id_t ptp_id, 289 int clock_num, 290 int *num_tod_sources, 291 bcm_ptp_tod_input_t *tod_sources) 292 { 293 int rv = BCM_E_UNAVAIL; 294 int i; 295 296 bcm_ptp_port_identity_t portid; 297 uint8 resp[PTP_MGMTMSG_PAYLOAD_CONFIGURE_TOD_IN_SIZE_OCTETS] = {0}; 298 int resp_len = PTP_MGMTMSG_PAYLOAD_CONFIGURE_TOD_IN_SIZE_OCTETS; 299 300 uint8 fmtlen = 0; 301 302 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 303 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 304 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 305 return rv; 306 } 307 308 if (*num_tod_sources >= PTP_MAX_TOD_INPUTS) { 309 *num_tod_sources = PTP_MAX_TOD_INPUTS; 310 } 311 312 if (PTP_TIMESOURCE_USE_MANAGEMENT_MSG) { 313 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 314 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 315 return rv; 316 } 317 318 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, 319 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_CONFIGURE_TOD_IN, 0, 0, 320 resp, &resp_len))) { 321 return rv; 322 } 323 324 /* 325 * Parse response. 326 * Octet 0...5 : Custom management message key/identifier. 327 * BCM<null><null><null>. 328 * Octet 6 : UART number. 329 * Octet 7..10 : ToD-In offset seconds 330 * Octet 11..14 : ToD-In offset nanoseconds 331 * Octet 15 : ToD-In format. 332 * Octet 16 : ToD-In format string length. 333 * Octet 17...48 : ToD-In format string. 334 * Octet 49 : ToD-In mask string length. 335 * Octet 50...177 : ToD-In mask string. 336 * Octet 178...183: SRC MAC. 337 * Octet 184...185: VLAN. 338 * Octet 186...187: Ethernet Type. 339 * Octet 188...191: ToD baud rate. 340 */ 341 tod_sources[0].source = resp[6]; 342 343 i = 7; 344 tod_sources[0].tod_offset_sec = (int32) _bcm_ptp_uint32_read(resp+i); i += 4; 345 tod_sources[0].tod_offset_ns = (int32) _bcm_ptp_uint32_read(resp+i); i += 4; 346 347 /* 348 * ToD format enumeration. 349 * Account for mapping to firmware definition. 350 */ 351 tod_sources[0].format = resp[i++] - 1; 352 353 fmtlen = resp[i++]; 354 sal_memset(tod_sources[0].format_str, 0, BCM_PTP_MAX_TOD_FORMAT_STRING); 355 sal_memcpy(tod_sources[0].format_str, resp + i, fmtlen); 356 i += PTP_TIMESOURCE_TODIN_MGMTMSG_FORMAT_LENGTH; 357 358 fmtlen = resp[i++]; 359 sal_memset(tod_sources[0].mask_str, 0, BCM_PTP_MAX_TOD_FORMAT_STRING); 360 sal_memcpy(tod_sources[0].mask_str, resp + i, fmtlen); 361 i += PTP_TIMESOURCE_TODIN_MGMTMSG_MASK_LENGTH; 362 363 /* advancing i to the offset of ToD baud rate */ 364 i+= 10; 365 366 if (resp_len >= PTP_MGMTMSG_PAYLOAD_CONFIGURE_TOD_IN_SIZE_OCTETS) { 367 /* read tod baud rate if received */ 368 tod_sources[0].tod_baud_rate = (uint32) _bcm_ptp_uint32_read(resp+i); i += 4; 369 } 370 371 } else { 372 for (i = 0; i < *num_tod_sources; ++i) { 373 if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_tod_input_get(unit, ptp_id, 374 clock_num, i, &tod_sources[i]))) { 375 return rv; 376 } 377 } 378 } 379 380 return BCM_E_NONE; 381 } 382 383 /* 384 * Function: 385 * bcm_common_ptp_timesource_input_status_get 386 * Purpose: 387 * Get time source status. 388 * Parameters: 389 * unit - (IN) Unit number. 390 * ptp_id - (IN) PTP stack ID. 391 * clock_num - (IN) PTP clock number. 392 * status - (OUT) Time source status. 393 * Returns: 394 * BCM_E_XXX - Function status. 395 * Notes: 396 */ 397 int 398 bcm_common_ptp_timesource_input_status_get( 399 int unit, 400 bcm_ptp_stack_id_t ptp_id, 401 int clock_num, 402 bcm_ptp_timesource_status_t *status) 403 { 404 return BCM_E_UNAVAIL; 405 } 406 407 /* 408 * Function: 409 * bcm_common_ptp_input_channels_set 410 * Purpose: 411 * Set PTP input channels. 412 * Parameters: 413 * unit - (IN) Unit number. 414 * ptp_id - (IN) PTP stack ID. 415 * clock_num - (IN) PTP clock number. 416 * num_channels - (IN) Number of channels (time sources). 417 * channels - (IN) Channels (time sources). 418 * Returns: 419 * BCM_E_XXX - Function status. 420 * Notes: 421 */ 422 int 423 bcm_common_ptp_input_channels_set( 424 int unit, 425 bcm_ptp_stack_id_t ptp_id, 426 int clock_num, 427 int num_channels, 428 bcm_ptp_channel_t *channels) 429 { 430 int rv = BCM_E_UNAVAIL; 431 int i; 432 433 bcm_ptp_port_identity_t portid; 434 uint8 payload[PTP_MGMTMSG_PAYLOAD_CHANNELS_SIZE_OCTETS] = {0}; 435 uint8 *curs = &payload[0]; 436 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 437 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 438 439 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 440 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 441 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 442 return rv; 443 } 444 445 446 447 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 448 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 449 return rv; 450 } 451 452 if (num_channels >= PTP_MAX_TIME_SOURCES) { 453 num_channels = PTP_MAX_TIME_SOURCES; 454 } else if (num_channels < 1) { 455 num_channels = 1; 456 } 457 458 /* 459 * Prescan channel definitions. 460 * Disallow set up of sixth GPIO as input channel on Tr3. 461 */ 462 if (PTP_CONDITIONAL_IS_TRIUMPH3(unit)) { 463 for (i = 0; i < num_channels; ++i) { 464 if (channels[i].source == (PTP_GPIO_OUTPUT_SIGNALS - 1)) { 465 LOG_ERROR(BSL_LS_BCM_COMMON, 466 (BSL_META_U(unit, 467 "PTP input channel error\n"))); 468 return BCM_E_PARAM; 469 } 470 } 471 } 472 473 /* Make payload. */ 474 _bcm_ptp_uint16_write(curs, num_channels); curs += sizeof(uint16); 475 476 for (i = 0; i < num_channels; ++i) { 477 _bcm_ptp_uint16_write(curs, channels[i].type); curs += sizeof(uint16); 478 _bcm_ptp_uint32_write(curs, channels[i].source); curs += sizeof(uint32); 479 _bcm_ptp_uint32_write(curs, channels[i].frequency); curs += sizeof(uint32); 480 481 *curs++ = channels[i].tod_index; 482 483 *curs++ = channels[i].freq_priority; 484 *curs++ = channels[i].freq_enabled; 485 *curs++ = channels[i].time_prio; 486 *curs++ = channels[i].time_enabled; 487 488 *curs++ = channels[i].freq_assumed_QL; 489 *curs++ = channels[i].time_assumed_QL; 490 *curs++ = channels[i].assumed_QL_enabled; 491 492 _bcm_ptp_uint32_write(curs, channels[i].resolution); curs += sizeof(uint32); 493 494 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 495 *curs++ = channels[i].synce_input_port; 496 if (PTP_UC_FEATURE_CHECK(PTP_CMICM_CHANNEL_CONF_L1BKUP)) { 497 *curs++ = channels[i].synce_input_clk_type; 498 } 499 if(PTP_UC_FEATURE_CHECK(PTP_CMICM_CHANNEL_CONF_NOL1MUXSEL)) { 500 _bcm_ptp_uint32_write(curs, channels[i].synce_config_flags); curs += sizeof(uint32); 501 } 502 } 503 } 504 505 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, &portid, 506 PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_CHANNELS, 507 payload, curs - payload, resp, &resp_len); 508 509 return rv; 510 } 511 512 /* 513 * Function: 514 * bcm_common_ptp_input_channels_get 515 * Purpose: 516 * Set PTP input channels. 517 * Parameters: 518 * unit - (IN) Unit number. 519 * ptp_id - (IN) PTP stack ID. 520 * clock_num - (IN) PTP clock number. 521 * num_channels - (IN/ Max number of channels (time sources) / 522 * OUT) Number of returned channels (time sources). 523 * channels - (OUT) Channels (time sources). 524 * Returns: 525 * BCM_E_XXX - Function status; 526 * Notes: 527 * Function is not part of external API at this point. 528 */ 529 int 530 bcm_common_ptp_input_channels_get( 531 int unit, 532 bcm_ptp_stack_id_t ptp_id, 533 int clock_num, 534 int *num_channels, 535 bcm_ptp_channel_t *channels) 536 { 537 int rv = BCM_E_UNAVAIL; 538 int i; 539 540 bcm_ptp_port_identity_t portid; 541 int max_num_channels = *num_channels; 542 543 uint8 resp[PTP_MGMTMSG_PAYLOAD_CHANNELS_SIZE_OCTETS] = {0}; 544 uint8 *curs = &resp[0]; 545 int resp_len = PTP_MGMTMSG_PAYLOAD_CHANNELS_SIZE_OCTETS; 546 547 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 548 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 549 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 550 return rv; 551 } 552 553 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 554 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 555 return rv; 556 } 557 558 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, &portid, 559 PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_CHANNELS, 0, 0, resp, &resp_len); 560 561 /* Parse response. */ 562 *num_channels = _bcm_ptp_uint16_read(curs); curs += sizeof(uint16); 563 564 if (*num_channels > max_num_channels) { 565 *num_channels = max_num_channels; 566 } 567 568 for (i = 0; i < *num_channels; ++i) { 569 channels[i].type = _bcm_ptp_uint16_read(curs); curs += sizeof(uint16); 570 channels[i].source = _bcm_ptp_uint32_read(curs); curs += sizeof(uint32); 571 channels[i].frequency = _bcm_ptp_uint32_read(curs); curs += sizeof(uint32); 572 channels[i].tod_index = *curs++; 573 channels[i].freq_priority = *curs++; 574 channels[i].freq_enabled = *curs++; 575 channels[i].time_prio = *curs++; 576 channels[i].time_enabled = *curs++; 577 channels[i].freq_assumed_QL = *curs++; 578 channels[i].time_assumed_QL = *curs++; 579 channels[i].assumed_QL_enabled = *curs++; 580 channels[i].resolution = _bcm_ptp_uint32_read(curs); curs += sizeof(uint32); 581 channels[i].synce_input_port = *curs++; 582 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 583 if (PTP_UC_FEATURE_CHECK(PTP_CMICM_CHANNEL_CONF_L1BKUP)) { 584 channels[i].synce_input_clk_type = (bcm_ptp_synce_clock_type_t)(*curs++); 585 } 586 if (PTP_UC_FEATURE_CHECK(PTP_CMICM_CHANNEL_CONF_NOL1MUXSEL)) { 587 channels[i].synce_config_flags= _bcm_ptp_uint32_read(curs); curs += sizeof(uint32); 588 } 589 } 590 } 591 592 return rv; 593 } 594 595 /* 596 * Function: 597 * _bcm_common_ptp_input_channels_status_get 598 * Purpose: 599 * Get status of channels 600 * Parameters: 601 * unit - (IN) Unit number. 602 * ptp_id - (IN) PTP stack ID. 603 * clock_num - (IN) PTP clock number. 604 * num_chan - (IN/OUT) Number of channels to return / returned 605 * chan_status - (OUT) Array of channel statuses 606 * Returns: 607 * BCM_E_XXX - Function status. 608 * Notes: 609 */ 610 int 611 _bcm_common_ptp_input_channels_status_get( 612 int unit, 613 bcm_ptp_stack_id_t ptp_id, 614 int clock_num, 615 int *num_chan, 616 _bcm_ptp_channel_status_t *chan_status) 617 { 618 int rv = BCM_E_UNAVAIL; 619 int i; 620 int num_returned_channels = 0; 621 622 uint8 resp[PTP_MGMTMSG_PAYLOAD_CHANNEL_STATUS_SIZE_OCTETS] = {0}; 623 uint8 *curs = &resp[6]; 624 int resp_len = PTP_MGMTMSG_PAYLOAD_CHANNEL_STATUS_SIZE_OCTETS; 625 626 bcm_ptp_port_identity_t portid; 627 628 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 629 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 630 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 631 return rv; 632 } 633 634 if (*num_chan < 1) { 635 return BCM_E_PARAM; 636 } 637 638 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 639 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 640 return rv; 641 } 642 643 if (BCM_FAILURE (rv = _bcm_ptp_management_message_send(unit, ptp_id, 644 clock_num, &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_CHANNEL_STATUS, 645 0, 0, resp, &resp_len))) { 646 return rv; 647 } 648 649 /* Parse response. */ 650 num_returned_channels = _bcm_ptp_uint16_read(curs); curs += sizeof(uint16); 651 652 if (num_returned_channels < *num_chan) { 653 *num_chan = num_returned_channels; 654 } 655 656 for (i = 0; i < *num_chan; ++i) { 657 chan_status[i].freq_status = _bcm_ptp_uint32_read(curs); 658 curs += sizeof(uint32); 659 chan_status[i].time_status = _bcm_ptp_uint32_read(curs); 660 curs += sizeof(uint32); 661 chan_status[i].freq_weight = _bcm_ptp_uint32_read(curs); 662 curs += sizeof(uint32); 663 chan_status[i].time_weight = _bcm_ptp_uint32_read(curs); 664 curs += sizeof(uint32); 665 chan_status[i].freq_QL = _bcm_ptp_uint32_read(curs); 666 curs += sizeof(uint32); 667 chan_status[i].time_QL = _bcm_ptp_uint32_read(curs); 668 curs += sizeof(uint32); 669 chan_status[i].ql_read_externally = _bcm_ptp_uint32_read(curs); 670 curs += sizeof(uint32); 671 chan_status[i].fault_map = _bcm_ptp_uint32_read(curs); 672 curs += sizeof(uint32); 673 } 674 675 return BCM_E_NONE; 676 } 677 678 679 680 /* 681 * Function: 682 * bcm_common_ptp_input_channel_precedence_mode_set 683 * Purpose: 684 * Set PTP input channels precedence mode. 685 * Parameters: 686 * unit - (IN) Unit number. 687 * ptp_id - (IN) PTP stack ID. 688 * clock_num - (IN) PTP clock number. 689 * channel_select_mode - (IN) Input channel precedence mode selector. 690 * Returns: 691 * BCM_E_XXX - Function status. 692 * Notes: 693 */ 694 int 695 bcm_common_ptp_input_channel_precedence_mode_set( 696 int unit, 697 bcm_ptp_stack_id_t ptp_id, 698 int clock_num, 699 int channel_select_mode) 700 { 701 return BCM_E_UNAVAIL; 702 } 703 704 /* 705 * Function: 706 * bcm_common_ptp_input_channel_switching_mode_set 707 * Purpose: 708 * Set PTP input channels switching mode. 709 * Parameters: 710 * unit - (IN) Unit number. 711 * ptp_id - (IN) PTP stack ID. 712 * clock_num - (IN) PTP clock number. 713 * channel_switching_mode - (IN) Channel switching mode selector. 714 * Returns: 715 * BCM_E_XXX - Function status. 716 * Notes: 717 */ 718 int 719 bcm_common_ptp_input_channel_switching_mode_set( 720 int unit, 721 bcm_ptp_stack_id_t ptp_id, 722 int clock_num, 723 int channel_switching_mode) 724 { 725 return BCM_E_UNAVAIL; 726 } 727 728 /* 729 * Function: 730 * bcm_common_ptp_tod_output_set 731 * Purpose: 732 * Set PTP ToD output. 733 * Parameters: 734 * unit - (IN) Unit number. 735 * ptp_id - (IN) PTP stack ID. 736 * clock_num - (IN) PTP clock number. 737 * tod_output_id - (OUT) ToD output ID. 738 * output_info - (IN) ToD output configuration. 739 * Returns: 740 * BCM_E_XXX - Function status. 741 * Notes: 742 */ 743 int 744 bcm_common_ptp_tod_output_set( 745 int unit, 746 bcm_ptp_stack_id_t ptp_id, 747 int clock_num, 748 int *tod_output_id, 749 bcm_ptp_tod_output_t *output_info) 750 { 751 int rv = BCM_E_UNAVAIL; 752 int fw_format_type = output_info->format + 1; /* relies on firmware format type having the same ordering */ 753 754 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 755 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 756 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 757 return rv; 758 } 759 760 if (output_info->source == bcmPTPTODSourceNone) { 761 LOG_INFO(BSL_LS_BCM_PTP, 762 (BSL_META_U(unit, 763 "Unexpected bcmPTPTODSourceNone as TOD output type\n"))); 764 return BCM_E_PARAM; 765 } 766 767 if (BCM_FAILURE(rv = _bcm_common_ptp_configure_serial_tod(unit, ptp_id, clock_num, 768 output_info->source, output_info->tod_offset_src, output_info->tod_offset_ns, output_info->tod_delay_ns, 769 fw_format_type, output_info->format_str_len, (char *)output_info->format_str, 770 output_info->peer_address.raw_l2_header_length, output_info->peer_address.raw_l2_header, 771 output_info->tod_baud_rate ))) { 772 return rv; 773 } 774 775 /* We support a single TOD output for each source, so just map source type to output ID */ 776 *tod_output_id = (int) output_info->source; 777 778 if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_tod_output_set(unit, ptp_id, clock_num, 779 *tod_output_id - 1, output_info))) { 780 return rv; 781 } 782 783 return BCM_E_NONE; 784 } 785 786 /* 787 * Function: 788 * bcm_common_ptp_tod_output_get 789 * Purpose: 790 * Get PTP TOD output(s). 791 * Parameters: 792 * unit - (IN) Unit number. 793 * ptp_id - (IN) PTP stack ID. 794 * clock_num - (IN) PTP clock number. 795 * tod_output_count - (IN/ Max number of ToD outputs / 796 * OUT) Number ToD outputs returned. 797 * tod_outputs - (OUT) Array of ToD outputs. 798 * Returns: 799 * BCM_E_XXX - Function status. 800 * Notes: 801 */ 802 int 803 bcm_common_ptp_tod_output_get( 804 int unit, 805 bcm_ptp_stack_id_t ptp_id, 806 int clock_num, 807 int *tod_output_count, 808 bcm_ptp_tod_output_t *tod_outputs) 809 { 810 int rv = BCM_E_UNAVAIL; 811 int i; 812 813 bcm_ptp_port_identity_t portid; 814 uint8 resp[PTP_MGMTMSG_PAYLOAD_CONFIGURE_TOD_OUT_SIZE_OCTETS] = {0}; 815 int resp_len = PTP_MGMTMSG_PAYLOAD_CONFIGURE_TOD_OUT_SIZE_OCTETS; 816 817 818 819 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 820 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 821 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 822 return rv; 823 } 824 825 if (*tod_output_count >= PTP_MAX_TOD_OUTPUTS) { 826 *tod_output_count = PTP_MAX_TOD_OUTPUTS; 827 } 828 829 if (PTP_TIMESOURCE_USE_MANAGEMENT_MSG) { 830 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 831 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 832 return rv; 833 } 834 835 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, 836 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_CONFIGURE_TOD_OUT, 0, 0, 837 resp, &resp_len))) { 838 return rv; 839 } 840 841 /* 842 * Parse response. 843 * Octet 0...5 : Custom management message key/identifier. 844 * BCM<null><null><null>. 845 * Octet 6 : UART number. 846 * Octet 7...14 : ToD-Out offset (nsec). 847 * Octet 15...18 : ToD-Out delay (nsec). 848 * Octet 19 : ToD-Out format. 849 * Octet 20 : ToD-Out format string length. 850 * Octet 21...148 : ToD-Out format string. 851 */ 852 tod_outputs[0].source = resp[6]; 853 tod_outputs[0].frequency = 1; 854 855 i = 7; 856 857 tod_outputs[0].tod_offset_src = _bcm_ptp_uint32_read(resp+i); 858 i += sizeof(uint32); 859 tod_outputs[0].tod_offset_ns = _bcm_ptp_uint32_read(resp+i); 860 i += sizeof(uint32); 861 862 tod_outputs[0].tod_delay_ns = _bcm_ptp_uint32_read(resp+i); 863 i += sizeof(uint32); 864 865 /* 866 * ToD format enumeration. 867 * Account for mapping to firmware definition. 868 */ 869 tod_outputs[0].format = resp[i++] - 1; 870 871 if (tod_outputs[0].format < bcmPTPTODFormatString) { 872 tod_outputs[0].format = bcmPTPTODFormatString; 873 } 874 875 tod_outputs[0].format_str_len = resp[i++]; 876 sal_memset(tod_outputs[0].format_str, 0, BCM_PTP_MAX_TOD_FORMAT_STRING); 877 sal_memcpy(tod_outputs[0].format_str, resp + i, tod_outputs[0].format_str_len); 878 i += 128; 879 880 sal_memset(tod_outputs[0].peer_address.raw_l2_header, 0, 18); 881 sal_memcpy(tod_outputs[0].peer_address.raw_l2_header, resp + i, 18); 882 i += 18; 883 884 if (resp_len >= PTP_MGMTMSG_PAYLOAD_CONFIGURE_TOD_OUT_SIZE_OCTETS) { 885 /* read tod baud rate if received */ 886 tod_outputs[0].tod_baud_rate = _bcm_ptp_uint32_read(resp+i); 887 i += sizeof(uint32); 888 } 889 890 } else { 891 for (i = 0; i < *tod_output_count; ++i) { 892 if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_tod_output_get(unit, ptp_id, 893 clock_num, i, &tod_outputs[i]))) { 894 return rv; 895 } 896 } 897 } 898 899 return BCM_E_NONE; 900 } 901 902 /* 903 * Function: 904 * bcm_common_ptp_tod_output_remove 905 * Purpose: 906 * Remove a ToD output. 907 * Parameters: 908 * unit - (IN) Unit number. 909 * ptp_id - (IN) PTP stack ID. 910 * clock_num - (IN) PTP clock number. 911 * tod_output_id - (IN) ToD output ID. 912 * Returns: 913 * BCM_E_XXX - Function status. 914 * Notes: 915 */ 916 int 917 bcm_common_ptp_tod_output_remove( 918 int unit, 919 bcm_ptp_stack_id_t ptp_id, 920 int clock_num, 921 int tod_output_id) 922 { 923 int rv = BCM_E_UNAVAIL; 924 int fw_format_type = 0; 925 926 if (BCM_FAILURE(rv = _bcm_common_ptp_configure_serial_tod(unit, ptp_id, clock_num, 927 tod_output_id, 0, 0, 0, fw_format_type, 0, 0, 0, 0, 0))) { 928 return rv; 929 } 930 931 return BCM_E_NONE; 932 } 933 934 /* 935 * Function: 936 * bcm_common_ptp_synce_output_set 937 * Purpose: 938 * Set SyncE output control on/off 939 * Parameters: 940 * unit - (IN) Unit number. 941 * ptp_id - (IN) PTP stack ID. 942 * clock_num - (IN) PTP clock number. 943 * synce_port - (IN) PTP output L1 clock port 944 * state - (IN) Non-zero to indicate that SyncE output should be controlled by TOP 945 * Returns: 946 * BCM_E_XXX - Function status. 947 * Notes: 948 */ 949 int 950 bcm_common_ptp_synce_output_set( 951 int unit, 952 bcm_ptp_stack_id_t ptp_id, 953 int clock_num, 954 int synce_port, 955 int state) 956 { 957 int rv = BCM_E_UNAVAIL; 958 959 bcm_ptp_port_identity_t portid; 960 uint8 payload[PTP_MGMTMSG_PAYLOAD_OUTPUT_SIGNALS_SIZE_OCTETS] = {0}; 961 uint8 *curs = &payload[0]; 962 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 963 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 964 965 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 966 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 967 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 968 return rv; 969 } 970 971 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 972 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 973 return rv; 974 } 975 976 _bcm_ptp_uint32_write(curs, state); 977 curs += sizeof(uint32); 978 *curs++ = synce_port; 979 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, &portid, 980 PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_OUTPUT_SYNCE, 981 payload, curs - payload, resp, &resp_len); 982 983 return rv; 984 } 985 986 987 /* 988 * Function: 989 * bcm_common_ptp_synce_output_get 990 * Purpose: 991 * Gets SyncE output control state 992 * Parameters: 993 * unit - (IN) Unit number. 994 * ptp_id - (IN) PTP stack ID. 995 * clock_num - (IN) PTP clock number. 996 * state - (OUT) Non-zero to indicate that SyncE output should be controlled by TOP 997 * Returns: 998 * BCM_E_XXX - Function status. 999 * Notes: 1000 */ 1001 int 1002 bcm_common_ptp_synce_output_get( 1003 int unit, 1004 bcm_ptp_stack_id_t ptp_id, 1005 int clock_num, 1006 int *state) 1007 { 1008 int rv = BCM_E_UNAVAIL; 1009 1010 bcm_ptp_port_identity_t portid; 1011 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1012 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1013 1014 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 1015 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1016 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1017 return rv; 1018 } 1019 1020 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 1021 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 1022 return rv; 1023 } 1024 1025 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, &portid, 1026 PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_OUTPUT_SYNCE, 1027 0, 0, 1028 resp, &resp_len); 1029 1030 if (resp_len < PTP_MGMTMSG_PAYLOAD_OUTPUT_SYNCE_SIZE_OCTETS) { 1031 /* Internal error : message too short to contain correct data. */ 1032 return BCM_E_INTERNAL; 1033 } 1034 1035 *state = _bcm_ptp_uint32_read(resp); 1036 1037 return rv; 1038 } 1039 1040 1041 /* 1042 * Function: 1043 * bcm_common_ptp_signal_output_set 1044 * Purpose: 1045 * Set PTP signal output. 1046 * Parameters: 1047 * unit - (IN) Unit number. 1048 * ptp_id - (IN) PTP stack ID. 1049 * clock_num - (IN) PTP clock number. 1050 * signal_output_id - (OUT) ID of signal. 1051 * output_info - (IN) Signal information. 1052 * Returns: 1053 * BCM_E_XXX - Function status. 1054 * Notes: 1055 */ 1056 int 1057 bcm_common_ptp_signal_output_set( 1058 int unit, 1059 bcm_ptp_stack_id_t ptp_id, 1060 int clock_num, 1061 int *signal_output_id, 1062 bcm_ptp_signal_output_t *output) 1063 { 1064 int rv = BCM_E_UNAVAIL; 1065 unsigned idx; 1066 1067 bcm_ptp_signal_output_t signal; 1068 bcm_ptp_port_identity_t portid; 1069 1070 uint8 payload[PTP_MGMTMSG_PAYLOAD_OUTPUT_SIGNALS_SIZE_OCTETS] = {0}; 1071 uint8 *curs = &payload[0]; 1072 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1073 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1074 1075 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 1076 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1077 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1078 return rv; 1079 } 1080 1081 idx = output->pin; 1082 if (idx >= PTP_MAX_OUTPUT_SIGNALS || 1083 (PTP_CONDITIONAL_IS_TRIUMPH3(unit) && idx == (PTP_GPIO_OUTPUT_SIGNALS-1))) { 1084 /* 1085 * Signal index verification. 1086 * Disallow set up of pin as output signal if index exceeds maximum pin number. 1087 * Disallow set up of sixth GPIO as output signal on Tr3. 1088 */ 1089 LOG_ERROR(BSL_LS_BCM_COMMON, 1090 (BSL_META_U(unit, 1091 "PTP signal index error\n"))); 1092 return BCM_E_PARAM; 1093 } 1094 1095 /* use the pin # as the signal_output_id, since they're unique anyhow */ 1096 /* this makes the "sparse" problem immediately apparent if the pin# is */ 1097 /* not zero, but the problem would occur anyhow if any but the first */ 1098 /* signal were removed */ 1099 1100 *signal_output_id = output->pin; 1101 1102 /* Special case for SyncE: use the SyncE output set message */ 1103 if (output->pin == PTP_OUTPUT_SIGNAL_SYNCE) { 1104 *signal_output_id = output->pin; 1105 return bcm_common_ptp_synce_output_set(unit, ptp_id, clock_num, output->synce_output_port, output->frequency); 1106 } 1107 1108 if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_signal_set(unit, ptp_id, clock_num, 1109 idx, output))) { 1110 return rv; 1111 } 1112 1113 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 1114 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 1115 return rv; 1116 } 1117 1118 /* Make payload. */ 1119 if (PTP_TIMESOURCE_USE_MANAGEMENT_MSG) { 1120 /* Get PTP signal output configurations from firmware. */ 1121 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 1122 clock_num, &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_OUTPUT_SIGNALS, 1123 0, 0, resp, &resp_len))) { 1124 return rv; 1125 } 1126 /* Insert updated configuration for chosen PTP signal output. */ 1127 sal_memcpy(payload, resp, PTP_MGMTMSG_PAYLOAD_OUTPUT_SIGNALS_SIZE_OCTETS); 1128 /* Advance cursor. */ 1129 curs += (output->pin*PTP_TIMESOURCE_SIGNAL_OUTPUT_DATA_SIZE_OCTETS); 1130 _bcm_ptp_uint32_write(curs, output->pin); 1131 curs += sizeof(uint32); 1132 _bcm_ptp_uint32_write(curs, output->frequency); 1133 curs += sizeof(uint32); 1134 *curs++ = output->phase_lock; 1135 _bcm_ptp_uint32_write(curs, output->pulse_width_ns); 1136 curs += sizeof(uint32); 1137 _bcm_ptp_uint32_write(curs, output->pulse_offset_ns); 1138 } else { 1139 /* Get PTP signal output configurations from SDK cache. */ 1140 for (idx = 0; idx < PTP_GPIO_OUTPUT_SIGNALS; ++idx) { 1141 if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_signal_get(unit, ptp_id, 1142 clock_num, idx, &signal))) { 1143 return rv; 1144 } 1145 _bcm_ptp_uint32_write(curs, signal.pin); curs += sizeof(uint32); 1146 _bcm_ptp_uint32_write(curs, signal.frequency); curs += sizeof(uint32); 1147 *curs++ = signal.phase_lock; 1148 _bcm_ptp_uint32_write(curs, signal.pulse_width_ns); curs += sizeof(uint32); 1149 _bcm_ptp_uint32_write(curs, signal.pulse_offset_ns); curs += sizeof(uint32); 1150 } 1151 } 1152 1153 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, &portid, 1154 PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_OUTPUT_SIGNALS, 1155 payload, PTP_MGMTMSG_PAYLOAD_OUTPUT_SIGNALS_SIZE_OCTETS, 1156 resp, &resp_len); 1157 1158 return rv; 1159 } 1160 1161 /* 1162 * Function: 1163 * bcm_common_ptp_signal_output_get 1164 * Purpose: 1165 * Get PTP signal output. 1166 * Parameters: 1167 * unit - (IN) Unit number. 1168 * ptp_id - (IN) PTP stack ID. 1169 * clock_num - (IN) PTP clock number. 1170 * signal_output_count - (IN/ Max number of signal outputs / 1171 * OUT) Number signal outputs returned. 1172 * signal_output - (OUT) Array of signal outputs. 1173 * Returns: 1174 * BCM_E_XXX - Function status. 1175 * Notes: 1176 * This function specification does not provide the ID of each signal, 1177 * so the signal ID equals the position in the array, i.e. there is no 1178 * mechanism to make it sparse. Invalid/inactive outputs are indicated 1179 * by a zero (0) frequency. 1180 */ 1181 int 1182 bcm_common_ptp_signal_output_get( 1183 int unit, 1184 bcm_ptp_stack_id_t ptp_id, 1185 int clock_num, 1186 int *signal_output_count, 1187 bcm_ptp_signal_output_t *signal_output) 1188 { 1189 int rv = BCM_E_UNAVAIL; 1190 int i; 1191 1192 bcm_ptp_port_identity_t portid; 1193 uint8 resp[PTP_MGMTMSG_PAYLOAD_OUTPUT_SIGNALS_SIZE_OCTETS] = {0}; 1194 uint8 *cursor = &resp[0]; 1195 int resp_len = PTP_MGMTMSG_PAYLOAD_OUTPUT_SIGNALS_SIZE_OCTETS; 1196 1197 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 1198 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1199 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1200 return rv; 1201 } 1202 1203 *signal_output_count = 0; 1204 1205 if (PTP_TIMESOURCE_USE_MANAGEMENT_MSG) { 1206 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 1207 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 1208 return rv; 1209 } 1210 1211 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, 1212 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_OUTPUT_SIGNALS, 1213 0, 0, resp, &resp_len))) { 1214 return rv; 1215 } 1216 1217 /* 1218 * Parse response. 1219 * Per Output Signal : # = Output Signal Number, I = 17(#-1) 1220 * Octet I...I+3 : Output Signal # pin. 1221 * Octet I+4...I+7 : Output Signal # frequency. 1222 * Octet I+8 : Output Signal # phase-lock Boolean. 1223 * Octet I+9...I+12 : Output Signal # pulse width (nsec). 1224 * Octet I+13...I+16 : Output Signal # pulse offset (nsec). 1225 */ 1226 for (i = 0; i < PTP_GPIO_OUTPUT_SIGNALS; ++i) { 1227 if (cursor >= (resp_len + &resp[0])) 1228 { 1229 return BCM_E_NONE; 1230 } 1231 signal_output[i].pin = _bcm_ptp_uint32_read(cursor); 1232 cursor += sizeof(uint32); 1233 signal_output[i].frequency = _bcm_ptp_uint32_read(cursor); 1234 cursor += sizeof(uint32); 1235 1236 signal_output[i].phase_lock = *cursor++; 1237 1238 signal_output[i].pulse_width_ns = _bcm_ptp_uint32_read(cursor); 1239 cursor += sizeof(uint32); 1240 signal_output[i].pulse_offset_ns = _bcm_ptp_uint32_read(cursor); 1241 cursor += sizeof(uint32); 1242 if (signal_output[i].frequency) 1243 { 1244 *signal_output_count = (*signal_output_count) + 1; 1245 } 1246 } 1247 1248 if (PTP_OUTPUT_SIGNAL_SYNCE > 0) { 1249 if (BCM_FAILURE(rv = bcm_common_ptp_synce_output_get(unit, ptp_id, clock_num, 1250 &signal_output[PTP_OUTPUT_SIGNAL_SYNCE].frequency))) { 1251 return rv; 1252 } 1253 if (signal_output[PTP_OUTPUT_SIGNAL_SYNCE].frequency) { 1254 *signal_output_count = (*signal_output_count) + 1; 1255 } 1256 signal_output[PTP_OUTPUT_SIGNAL_SYNCE].pin = PTP_OUTPUT_SIGNAL_SYNCE; 1257 signal_output[PTP_OUTPUT_SIGNAL_SYNCE].phase_lock = 0; 1258 signal_output[PTP_OUTPUT_SIGNAL_SYNCE].pulse_width_ns = 0; 1259 signal_output[PTP_OUTPUT_SIGNAL_SYNCE].pulse_offset_ns = 0; 1260 } 1261 } else { 1262 for (i = 0; i < *signal_output_count; ++i) { 1263 if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_signal_get(unit, ptp_id, 1264 clock_num, i, signal_output))) { 1265 return rv; 1266 } 1267 1268 ++signal_output; 1269 } 1270 } 1271 1272 return BCM_E_NONE; 1273 } 1274 1275 /* 1276 * Function: 1277 * bcm_common_ptp_signal_output_remove 1278 * Purpose: 1279 * Remove PTP signal output. 1280 * Parameters: 1281 * unit - (IN) Unit number. 1282 * ptp_id - (IN) PTP stack ID. 1283 * clock_num - (IN) PTP clock number. 1284 * signal_output_id - (IN) Signal to remove/invalidate. 1285 * Returns: 1286 * BCM_E_XXX - Function status. 1287 * Notes: 1288 */ 1289 int 1290 bcm_common_ptp_signal_output_remove( 1291 int unit, 1292 bcm_ptp_stack_id_t ptp_id, 1293 int clock_num, 1294 int signal_output_id) 1295 { 1296 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 1297 bcm_ptp_signal_output_t signal_output = {0}; 1298 signal_output.pin = signal_output_id; 1299 1300 return bcm_common_ptp_signal_output_set(unit, ptp_id, clock_num, &signal_output_id, &signal_output); 1301 } 1302 1303 return BCM_E_UNAVAIL; 1304 } 1305 1306 1307 /* 1308 * Function: 1309 * bcm_common_ptp_sync_phy 1310 * Purpose: 1311 * Instruct TOP to send a PHY Sync pulse, and mark the time that the PHYs are now synced to 1312 * Parameters: 1313 * unit - (IN) Unit number. 1314 * ptp_id - (IN) PTP stack ID. 1315 * clock_num - (IN) PTP clock number. 1316 * bcm_ptp_sync_phy_input_t (IN) PTP PHY SYNC inputs. 1317 * Returns: 1318 * BCM_E_XXX - Function status. 1319 * Notes: 1320 */ 1321 int 1322 bcm_common_ptp_sync_phy( 1323 int unit, 1324 bcm_ptp_stack_id_t ptp_id, 1325 int clock_num, 1326 bcm_ptp_sync_phy_input_t sync_input) 1327 { 1328 int rv = BCM_E_UNAVAIL; 1329 1330 bcm_ptp_port_identity_t portid = portid_all; 1331 uint8 payload[PTP_MGMTMSG_PAYLOAD_SYNC_PHY_SIZE_OCTETS] = {0}; 1332 uint8 resp[PTP_MGMTMSG_PAYLOAD_MAX_SIZE_OCTETS] = {0}; 1333 int resp_len = PTP_MGMTMSG_PAYLOAD_MAX_SIZE_OCTETS; 1334 uint8 *curs = payload; 1335 1336 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 1337 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1338 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1339 return rv; 1340 } 1341 1342 /* 1343 * Make payload. 1344 * Octet 0...2 : Custom management message key/identifier. 1345 * Octet 0= 'B'; Octet 1= 'C'; Octet 2= 'M'. 1346 * Octet 3...5 : Reserved. 1347 * Octet 6 : Framesync Pin # 1348 * Octet 7-14 : Reference time 1349 * Octet 15 : Freq Pin # 1350 */ 1351 1352 sal_memcpy(curs, "BCM\0\0\0", 6); curs += 6; 1353 *curs++ = sync_input.framesync_pin; 1354 _bcm_ptp_uint64_write(curs, sync_input.reference_time); curs += 8; 1355 *curs++ = sync_input.freq_pin; 1356 1357 portid = portid_all; 1358 1359 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, &portid, 1360 PTP_MGMTMSG_CMD, PTP_MGMTMSG_ID_SYNC_PHY, 1361 payload, curs - payload, resp, &resp_len); 1362 1363 return rv; 1364 1365 } 1366 1367 /* 1368 * Function: 1369 * bcm_common_ptp_bs_time_info_get 1370 * Purpose: 1371 * Instruct TOP to send a PHY Sync pulse, and mark the time that the PHYs are now synced to 1372 * Parameters: 1373 * unit - (IN) Unit number. 1374 * ptp_id - (IN) PTP stack ID. 1375 * clock_num - (IN) PTP clock number. 1376 * bcm_ptp_bs_time_info_t (OUT) TDPLL PHYTIME outputs. 1377 * Returns: 1378 * BCM_E_XXX - Function status. 1379 * Notes: 1380 */ 1381 int 1382 bcm_common_ptp_bs_time_info_get( 1383 int unit, 1384 bcm_ptp_stack_id_t ptp_id, 1385 int clock_num, 1386 bcm_ptp_bs_time_info_t *time) 1387 { 1388 int rv = BCM_E_UNAVAIL; 1389 bcm_ptp_port_identity_t portid = portid_all; 1390 1391 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS] = {0}; 1392 uint8 *curs = &resp[0]; 1393 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1394 1395 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 1396 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1397 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1398 return rv; 1399 } 1400 1401 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, &portid, 1402 PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_SYNC_PHYTIME, 0, 0, resp, &resp_len); 1403 1404 /* Parse response. */ 1405 time->bshb0_time = _bcm_ptp_uint64_read(curs+6); curs += sizeof(int64); 1406 time->bshb1_time = _bcm_ptp_uint64_read(curs+6); curs += sizeof(int64); 1407 /* 1408 * Parse response. 1409 * Octet 0...5 : Custom management message key/identifier. 1410 * BCM<null><null><null>. 1411 * Octet 6....14 : BS0 Stack local time (sec). 1412 * Octet 15...19 : BS0 stack local time (nsec). 1413 * Octet 20...28 : BS1 Stack local time (sec). 1414 * Octet 29...32 : BS1 stack local time (nsec). 1415 */ 1416 1417 time->systime_bs0_sec = _bcm_ptp_int64_read(curs + 6); curs += sizeof(int64); 1418 time->systime_bs0_nsec = _bcm_ptp_uint32_read(curs + 6); curs += 4; 1419 1420 time->systime_bs1_sec = _bcm_ptp_int64_read(curs + 6); curs += sizeof(int64); 1421 time->systime_bs1_nsec = _bcm_ptp_uint32_read(curs + 6); 1422 1423 return rv; 1424 } 1425 1426 /* 1427 * Function: 1428 * bcm_common_ptp_external_phy_synchronize() 1429 * Purpose: 1430 * Run state machine to synchronize CMIC time with external PHY time. 1431 * Parameters: 1432 * unit - (IN) Unit number. 1433 * stack_id - (IN) Stack identifier index. 1434 * clock_num - (IN) clock index. 1435 * extphy_config - (IN) external PHY config. 1436 * Returns: 1437 * BCM_E_XXX - Function status. 1438 * Notes: 1439 */ 1440 int 1441 bcm_common_ptp_external_phy_synchronize( 1442 int unit, 1443 int stack_id, 1444 int clock_num, 1445 bcm_ptp_external_phy_config_t extphy_config) 1446 { 1447 int rv = BCM_E_NONE; 1448 bcm_ptp_sync_phy_input_t sync_input; 1449 bcm_ptp_bs_time_info_t bshblocalTime ; 1450 uint64 physyncTime_nsec; 1451 uint8 physync_reqd = 0; 1452 int tmp = 0, tmp1= 0; 1453 1454 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1455 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1456 bcm_ptp_port_identity_t portid; 1457 1458 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, clock_num, 1459 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1460 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1461 return rv; 1462 } 1463 1464 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 1465 clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) { 1466 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 1467 return rv; 1468 } 1469 1470 for (tmp = 0; tmp <5; tmp++) { 1471 1472 bsl_printf("PHY synchronization iteration..: %d\n", tmp); 1473 1474 /* NEW API implemented to query the BSHB0/1 time when TDPLL is running */ 1475 1476 rv = bcm_common_ptp_bs_time_info_get(unit, stack_id, clock_num, &bshblocalTime); 1477 1478 if (rv) { 1479 bsl_printf("Issue with bcm_ptp_sync_phyTime API response from TDPLL fw.....Error code:%d\n",rv); 1480 return rv; 1481 } 1482 1483 1484 /* Perform initial framesync, so that pin is pulled low */ 1485 sal_memset(&sync_input, 0, sizeof(bcm_ptp_sync_phy_input_t)); 1486 sync_input.framesync_pin = extphy_config.framesync_pin; 1487 sync_input.freq_pin= extphy_config.freq_pin; 1488 1489 /* 1490 * PHY synchronization. 1491 * Calculate reference phase to program PHYs. 1492 * Reference phase based on local time (i.e. when stack is queried for 1493 * PHY synchronization state) plus sufficient delta to guarantee stack 1494 * can receive and process PHY framesync at BSHB which corresponds to 1495 * programmed phase. 1496 */ 1497 if(extphy_config.freq_pin == bcm_ptp_extphy_freq_pin_bs1_hb) { /*BSHB1 timestamp*/ 1498 physyncTime_nsec = bshblocalTime.bshb1_time; 1499 } else { 1500 physyncTime_nsec = bshblocalTime.bshb0_time; 1501 } 1502 1503 /* Adding CPU latecy - normally 1.5 sec */ 1504 COMPILER_64_ADD_64(physyncTime_nsec, extphy_config.cpu_latency_nsec); 1505 1506 /* For 54240 PHY , REF_PHASE = {REF_PHASE_2(15:0),REF_PHASE_1(15:0)_,REF_PHASE_0(15:0)} 1507 * Note : REF_PHASE is 48bits unlike LOCAL_TIME which is 44bits 1508 */ 1509 sync_input.reference_time = physyncTime_nsec; 1510 1511 /* Perform initial framesync, so that pin is pulled low */ 1512 rv = bcm_common_ptp_sync_phy(unit, stack_id, clock_num, sync_input); 1513 if (rv) { 1514 return rv; 1515 } 1516 1517 /* delay 1ms for the framesync to happen */ 1518 sal_usleep(1000); 1519 1520 bsl_printf("Calling External PHY configuration function ..\n"); 1521 if (extphy_config.ext_physync_func) { 1522 extphy_config.ext_physync_func(unit, stack_id, clock_num, extphy_config.pbm, physyncTime_nsec); 1523 } 1524 1525 /* Perform the actual framesync so that programmed PHY values are loaded */ 1526 rv = bcm_common_ptp_sync_phy(unit, stack_id, clock_num, sync_input); 1527 1528 #ifdef COMPILER_HAS_LONGLONG 1529 /*Debug logs added here to avoid any latency */ 1530 if(bcm_ptp_extphy_freq_pin_bs1_hb == extphy_config.freq_pin) { /*BSHB1 timestamp*/ 1531 bsl_printf("****BS1 selected for SYNC_IN0 ,BS1 HB Time:%lld\n",(long long)bshblocalTime.bshb1_time); 1532 bsl_printf("REF_PHASE Configured with value : %lld\n",(long long)physyncTime_nsec); 1533 } else { /*default BSHB0 timestamp */ 1534 bsl_printf("****BS0 selected for SYNC_IN0 ,BS0 HB Time:%lld\n",(long long)bshblocalTime.bshb0_time); 1535 bsl_printf("REF_PHASE Configured with value : %lld\n",(long long)physyncTime_nsec); 1536 } 1537 #endif 1538 1539 for (tmp1=0; tmp1<10; tmp1++) { 1540 /* Query stack to determine whether PHY synchronization is required. */ 1541 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, 1542 clock_num, &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_PHYSYNC_STATE, 1543 0, 0, resp, &resp_len))) { 1544 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 1545 return rv; 1546 } 1547 1548 /* 1549 * Parse response. 1550 * Octet 0...5 : Custom management message key/identifier. 1551 * BCM<null><null><null>. 1552 * Octet 6 : PHY synchronization required Boolean. 1553 * Octet 7 : Reserved. 1554 * Octet 8...15 : Stack local time (sec). 1555 * Octet 16...19: stack local time (nsec). 1556 */ 1557 physync_reqd = resp[6]; 1558 1559 /* PHY synchronization. */ 1560 if (physync_reqd == _bcm_ptp_physync_state_synchronized) { 1561 /* PHY synchronization is not required. */ 1562 bsl_printf("PHY synchronization complete or not required %d\n", physync_reqd); 1563 return rv; 1564 } 1565 else { 1566 bsl_printf("PHY synchronization state %d\n", physync_reqd); 1567 sal_sleep(1); 1568 continue; 1569 } 1570 } 1571 } 1572 1573 bsl_printf("PHY synchronization failed ......\n"); 1574 1575 return rv; 1576 } 1577 #endif /* defined(INCLUDE_PTP)*/