tdpll_dpll.c (32632B)
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: tdpll.c 8 * 9 * Purpose: Telecom DPLL logical DPLL instance configuration and management. 10 * 11 * Functions: 12 * bcm_tdpll_dpll_instance_init 13 * bcm_tdpll_dpll_bindings_get 14 * bcm_tdpll_dpll_bindings_set 15 * bcm_tdpll_dpll_reference_get 16 * bcm_tdpll_dpll_reference_set 17 * bcm_tdpll_dpll_bandwidth_get 18 * bcm_tdpll_dpll_bandwidth_set 19 * bcm_tdpll_dpll_phase_control_get 20 * bcm_tdpll_dpll_phase_control_set 21 */ 22 23 #if defined(INCLUDE_PTP) 24 25 #include <bcm/ptp.h> 26 #include <bcm_int/common/ptp.h> 27 #include <bcm_int/ptp_common.h> 28 #include <bcm/error.h> 29 30 /* Definitions. */ 31 #define TDPLL_DPLL_BANDWIDTH_DEFAULT_VALUE (1) 32 #define TDPLL_DPLL_BANDWIDTH_DEFAULT_UNITS (bcm_tdpll_dpll_bandwidth_Hz) 33 #define TDPLL_DPLL_PHASEMODE_DEFAULT (bcm_tdpll_dpll_phase_mode_pbo) 34 35 #define DPLL(dpll_index) \ 36 (objdata.dpll_instance[dpll_index]) 37 38 /* Macros. */ 39 40 /* Types. */ 41 42 /* Constants and variables. */ 43 static bcm_tdpll_dpll_instance_data_t objdata; 44 45 /* Static functions. */ 46 47 #if defined(BCM_MONTEREY_SUPPORT) & defined(INCLUDE_GDPLL) 48 extern int _bcm_esw_tdpllOutinstance_bind(int unit, int outclock_index, uint32 tdpll_instance_num); 49 #endif 50 51 52 /* 53 * Function: 54 * bcm_tdpll_dpll_instance_init() 55 * Purpose: 56 * Initialize T-DPLL logical DPLL instance configuration and management data. 57 * Parameters: 58 * unit - (IN) Unit number. 59 * stack_id - (IN) PTP stack ID. 60 * Returns: 61 * BCM_E_XXX - Function status. 62 * Notes: 63 */ 64 int 65 bcm_tdpll_dpll_instance_init( 66 int unit, 67 int stack_id) 68 { 69 int i; 70 71 /*Initialize DPLL instances. */ 72 for (i = 0; i < TDPLL_DPLL_INSTANCE_NUM_MAX; ++i) { 73 /* Identification attributes. */ 74 DPLL(i).index = i; 75 76 /* DPLL input bindings. */ 77 SHR_BITSET_RANGE(DPLL(i).bindings.input_clocks, 0, TDPLL_INPUT_CLOCK_NUM_MAX); 78 79 /* DPLL output bindings. */ 80 SHR_BITCLR_RANGE(DPLL(i).bindings.output_clocks, 0, TDPLL_OUTPUT_CLOCK_NUM_MAX); 81 SHR_BITSET(DPLL(i).bindings.output_clocks, i); 82 83 /* 84 * DPLL configuration properties. 85 * - bandwidth : DPLL bandwidth. 86 * - phase_control : Output phase control properties. 87 */ 88 DPLL(i).properties.bandwidth.value = TDPLL_DPLL_BANDWIDTH_DEFAULT_VALUE; 89 DPLL(i).properties.bandwidth.units = TDPLL_DPLL_BANDWIDTH_DEFAULT_UNITS; 90 91 DPLL(i).properties.phase_control.mode = TDPLL_DPLL_PHASEMODE_DEFAULT; 92 DPLL(i).properties.phase_control.offset_ns = 0; 93 94 /* DPLL reference. */ 95 DPLL(i).reference = -1; 96 } 97 98 return BCM_E_NONE; 99 } 100 101 /* 102 * Function: 103 * bcm_tdpll_dpll_instance_cleanup() 104 * Purpose: 105 * Uninitialize T-DPLL logical DPLL instance configuration and management data. 106 * Parameters: 107 * unit - (IN) Unit number. 108 * stack_id - (IN) PTP stack ID. 109 * Returns: 110 * BCM_E_XXX - Function status. 111 * Notes: 112 */ 113 int 114 bcm_tdpll_dpll_instance_cleanup( 115 int unit, 116 int stack_id) 117 { 118 return BCM_E_NONE; 119 } 120 121 /* 122 * Function: 123 * bcm_tdpll_dpll_bindings_get() 124 * Purpose: 125 * Get logical DPLL instance input/output bindings. 126 * Parameters: 127 * unit - (IN) Unit number. 128 * stack_id - (IN) Stack identifier index. 129 * dpll_index - (IN) DPLL instance number. 130 * bindings - (OUT) DPLL instance bindings. 131 * Returns: 132 * BCM_E_XXX - Function status. 133 * Notes: 134 */ 135 int 136 bcm_common_tdpll_dpll_bindings_get( 137 int unit, 138 int stack_id, 139 int dpll_index, 140 bcm_tdpll_dpll_bindings_t *bindings) 141 { 142 int i; 143 int el; 144 int rv; 145 146 uint8 resp[PTP_MGMTMSG_PAYLOAD_TDPLL_BINDINGS_SIZE_OCTETS] = {0}; 147 int resp_len = PTP_MGMTMSG_PAYLOAD_TDPLL_BINDINGS_SIZE_OCTETS; 148 149 bcm_ptp_port_identity_t portid; 150 151 if (dpll_index < 0 || dpll_index >= TDPLL_DPLL_INSTANCE_NUM_MAX) { 152 return BCM_E_PARAM; 153 } 154 155 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 156 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 157 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 158 return rv; 159 } 160 161 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 162 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 163 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 164 return rv; 165 } 166 167 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 168 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_TDPLL_BINDINGS, 169 0, 0, resp, &resp_len))) { 170 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 171 return rv; 172 } 173 174 /* 175 * Parse response. 176 * Octet 0...5 : Custom management message key/identifier. 177 * BCM<null><null><null>. 178 * Octet 6 : Index, DPLL instance 0. 179 * Octet 7 : Reserved. 180 * Octet 8...11 : Input clocks, DPLL instance 0. 181 * Octet 12...15 : Output clocks, DPLL instance 0. 182 * Octet 16 : Index, DPLL instance 1. 183 * Octet 17 : Reserved. 184 * Octet 18...21 : Input clocks, DPLL instance 1. 185 * Octet 22...25 : Output clocks, DPLL instance 1. 186 * Octet 26 : Index, DPLL instance 2. 187 * Octet 27 : Reserved. 188 * Octet 28...31 : Input clocks, DPLL instance 2. 189 * Octet 32...35 : Output clocks, DPLL instance 2. 190 * Octet 36 : Index, DPLL instance 3. 191 * Octet 37 : Reserved. 192 * Octet 38...41 : Input clocks, DPLL instance 3. 193 * Octet 42...45 : Output clocks, DPLL instance 3. 194 * Octet 46 : Index, DPLL instance 4. 195 * Octet 47 : Reserved. 196 * Octet 48...51 : Input clocks, DPLL instance 4. 197 * Octet 52...55 : Output clocks, DPLL instance 4. 198 * Octet 56 : Index, DPLL instance 5. 199 * Octet 57 : Reserved. 200 * Octet 58...61 : Input clocks, DPLL instance 5. 201 * Octet 62...65 : Output clocks, DPLL instance 5. 202 * Octet 66 : Index, DPLL instance 5. 203 * Octet 67 : Reserved. 204 * Octet 68...71 : Input clocks, DPLL instance 6. 205 * Octet 72...75 : Output clocks, DPLL instance 6. 206 */ 207 i = 6; 208 for (el = 0; el < TDPLL_DPLL_INSTANCE_NUM_MAX; ++el) { 209 DPLL(el).index = resp[i++]; 210 i++; 211 212 213 DPLL(el).bindings.input_clocks[0] = _bcm_ptp_uint32_read(resp + i); 214 i += 4; 215 216 DPLL(el).bindings.output_clocks[0] = _bcm_ptp_uint32_read(resp + i); 217 i += 4; 218 } 219 220 *bindings = DPLL(dpll_index).bindings; 221 return BCM_E_NONE; 222 } 223 224 /* 225 * Function: 226 * bcm_tdpll_dpll_bindings_set() 227 * Purpose: 228 * Set logical DPLL instance input/output bindings. 229 * Parameters: 230 * unit - (IN) Unit number. 231 * stack_id - (IN) Stack identifier index. 232 * dpll_index - (IN) DPLL instance number. 233 * bindings - (IN) DPLL instance bindings. 234 * Returns: 235 * BCM_E_XXX - Function status. 236 * Notes: 237 */ 238 int 239 bcm_common_tdpll_dpll_bindings_set( 240 int unit, 241 int stack_id, 242 int dpll_index, 243 bcm_tdpll_dpll_bindings_t *bindings) 244 { 245 int i; 246 int el; 247 int rv; 248 #if defined (BCM_MONTEREY_SUPPORT) 249 int j; 250 int k; 251 uint8 num_instance_per_msg = 10; 252 uint8 *num_instance_ptr = NULL; 253 #endif 254 255 uint8 payload[PTP_MGMTMSG_PAYLOAD_TDPLL_BINDINGS_SIZE_OCTETS] = {0}; 256 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 257 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 258 bcm_ptp_port_identity_t portid; 259 uint32 output_mask; 260 261 if (dpll_index < 0 || dpll_index >= TDPLL_DPLL_INSTANCE_NUM_MAX) { 262 return BCM_E_PARAM; 263 } 264 265 #if defined (BCM_MONTEREY_SUPPORT) 266 num_instance_per_msg = TDPLL_DPLL_INSTANCE_NUM_MAX > 10 ? 10: TDPLL_DPLL_INSTANCE_NUM_MAX; 267 #endif 268 269 DPLL(dpll_index).bindings = *bindings; 270 271 #if defined (BCM_MONTEREY_SUPPORT) 272 /* Limit input/output clock assignments to valid masks. */ 273 DPLL(dpll_index).bindings.input_clocks[_SHR_BITDCLSIZE(TDPLL_INPUT_CLOCK_NUM_MAX)-1] &= 274 ((1 << (TDPLL_INPUT_CLOCK_NUM_MAX % SHR_BITWID)) - 1); 275 276 DPLL(dpll_index).bindings.output_clocks[_SHR_BITDCLSIZE(TDPLL_OUTPUT_CLOCK_NUM_MAX)-1] &= 277 ((1 << (TDPLL_OUTPUT_CLOCK_NUM_MAX % SHR_BITWID)) - 1); 278 279 #else 280 /* Limit input/output clock assignments to valid masks. */ 281 282 DPLL(dpll_index).bindings.input_clocks[0] &= ((1 << TDPLL_INPUT_CLOCK_NUM_MAX) - 1); 283 284 DPLL(dpll_index).bindings.output_clocks[0] &= ((1 << TDPLL_OUTPUT_CLOCK_NUM_MAX) - 1); 285 286 /* Reject output clock bindings for XGPLL2/PMHPLL and XGPLL3 if not supported by h/w */ 287 if (!soc_feature(unit, soc_feature_tdpll_outputclk_synce3)) { 288 if (TDPLL_OUTPUT_CLOCK_SYNCE3_PLL_ENABLED( DPLL(dpll_index).bindings.output_clocks[0])) { 289 return BCM_E_PARAM; 290 } 291 } 292 293 if (!soc_feature(unit, soc_feature_tdpll_outputclk_xgpll3)) { 294 if (TDPLL_OUTPUT_CLOCK_SYNCE_XGPLL3_ENABLED( DPLL(dpll_index).bindings.output_clocks[0]) ) { 295 return BCM_E_PARAM; 296 } 297 } 298 #endif 299 300 #if defined(BCM_MONTEREY_SUPPORT) & defined(INCLUDE_GDPLL) 301 /* Bind the output clock(synthesizer) to the instance */ 302 for (j = 0; j < TDPLL_OUTPUT_CLOCK_NUM_MAX; j++) { 303 output_mask = DPLL(dpll_index).bindings.output_clocks[_SHR_BITDCLSIZE(j+1)-1]; 304 305 /* Get the bit position */ 306 i = j - (j/32)*32; 307 308 /* If the mask is set for outclock, call the gdpll instance bind to output */ 309 if (output_mask & (1 << i)) { 310 _bcm_esw_tdpllOutinstance_bind(unit, j, dpll_index); 311 } 312 } 313 #endif 314 315 /* Update reference-selection and switching logic with input-DPLL bindings. */ 316 for (el = 0; el < TDPLL_INPUT_CLOCK_NUM_MAX; ++el) { 317 if (BCM_FAILURE(rv = bcm_tdpll_input_clock_dpll_use_set(unit, stack_id, el, 318 dpll_index, SHR_BITGET(DPLL(dpll_index).bindings.input_clocks, el)))) { 319 PTP_ERROR_FUNC("bcm_tdpll_dpll_instance_set()"); 320 continue; 321 } 322 } 323 324 /* 325 * Reconcile output clock assignments of DPLL instances. 326 * NOTE: Each synthesizer (output clock) only bindable to one DPLL instance. 327 */ 328 329 #if defined(BCM_MONTEREY_SUPPORT) 330 for (el = 0; el < TDPLL_DPLL_INSTANCE_NUM_MAX; ++el) { 331 output_mask = DPLL(dpll_index).bindings.output_clocks[el/SHR_BITWID]; 332 if (dpll_index == el) { 333 continue; 334 } 335 DPLL(el).bindings.output_clocks[el/SHR_BITWID] ^= (output_mask & DPLL(el % SHR_BITWID).bindings.output_clocks[el/SHR_BITWID]); 336 output_mask |= DPLL(el).bindings.output_clocks[el/SHR_BITWID]; 337 } 338 #else 339 340 output_mask = DPLL(dpll_index).bindings.output_clocks[0]; 341 for (el = 0; el < TDPLL_DPLL_INSTANCE_NUM_MAX; ++el) { 342 if (dpll_index == el) { 343 continue; 344 } 345 DPLL(el).bindings.output_clocks[0] ^= (output_mask & DPLL(el).bindings.output_clocks[0]); 346 output_mask |= DPLL(el).bindings.output_clocks[0]; 347 } 348 #endif 349 350 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 351 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 352 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 353 return rv; 354 } 355 356 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 357 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 358 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 359 return rv; 360 } 361 362 /* 363 * Make payload. 364 * Octet 0...5 : Custom management message key/identifier. 365 * BCM<null><null><null>. 366 * Octet 6 : Index, DPLL instance 0. 367 * Octet 7 : Reserved. 368 * Octet 8...11 : Input clocks, DPLL instance 0. 369 * Octet 12...15 : Output clocks, DPLL instance 0. 370 * Octet 16 : Index, DPLL instance 1. 371 * Octet 17 : Reserved. 372 * Octet 18...21 : Input clocks, DPLL instance 1. 373 * Octet 22...25 : Output clocks, DPLL instance 1. 374 * Octet 26 : Index, DPLL instance 2. 375 * Octet 27 : Reserved. 376 * Octet 28...31 : Input clocks, DPLL instance 2. 377 * Octet 32...35 : Output clocks, DPLL instance 2. 378 * Octet 36 : Index, DPLL instance 3. 379 * Octet 37 : Reserved. 380 * Octet 38...41 : Input clocks, DPLL instance 3. 381 * Octet 42...45 : Output clocks, DPLL instance 3. 382 * Octet 46 : Index, DPLL instance 4. 383 * Octet 47 : Reserved. 384 * Octet 48...51 : Input clocks, DPLL instance 4. 385 * Octet 52...55 : Output clocks, DPLL instance 4. 386 * Octet 56 : Index, DPLL instance 5. 387 * Octet 57 : Reserved. 388 * Octet 58...61 : Input clocks, DPLL instance 5. 389 * Octet 62...65 : Output clocks, DPLL instance 5. 390 * Octet 66 : Index, DPLL instance 5. 391 * Octet 67 : Reserved. 392 * Octet 68...71 : Input clocks, DPLL instance 6. 393 * Octet 72...75 : Output clocks, DPLL instance 6. 394 */ 395 #if defined (BCM_MONTEREY_SUPPORT) 396 for (k = 0; k < TDPLL_DPLL_INSTANCE_NUM_MAX; k+=num_instance_per_msg) { 397 sal_memcpy(payload, "BCM\0\0\0", 6); 398 i = 6; 399 num_instance_ptr = &(payload[i]); 400 i++; 401 payload[i++] = 0; 402 403 for (el = k; (el < (k + num_instance_per_msg) && (el < TDPLL_DPLL_INSTANCE_NUM_MAX)); ++el) { 404 payload[i++] = (uint8)DPLL(el).index; 405 payload[i++] = 0; 406 407 for (j = 0; j < _SHR_BITDCLSIZE(BCM_TDPLL_INPUT_CLOCK_NUM_MAX); j++) { 408 _bcm_ptp_uint32_write(payload+i, DPLL(el).bindings.input_clocks[j]); 409 i += 4; 410 } 411 412 for (j = 0; j < _SHR_BITDCLSIZE(BCM_TDPLL_OUTPUT_CLOCK_NUM_MAX); j++) { 413 _bcm_ptp_uint32_write(payload+i, DPLL(el).bindings.output_clocks[j]); 414 i += 4; 415 } 416 } 417 418 *num_instance_ptr = (uint8)(el - k); 419 420 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 421 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_TDPLL_BINDINGS, 422 payload, PTP_MGMTMSG_PAYLOAD_TDPLL_BINDINGS_SIZE_OCTETS, 423 resp, &resp_len))) { 424 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 425 return rv; 426 } 427 428 } 429 #else 430 sal_memcpy(payload, "BCM\0\0\0", 6); 431 i = 6; 432 for (el = 0; el < TDPLL_DPLL_INSTANCE_NUM_MAX; ++el) { 433 payload[i++] = (uint8)DPLL(el).index; 434 payload[i++] = 0; 435 436 437 _bcm_ptp_uint32_write(payload+i, DPLL(el).bindings.input_clocks[0]); 438 i += 4; 439 440 _bcm_ptp_uint32_write(payload+i, DPLL(el).bindings.output_clocks[0]); 441 i += 4; 442 } 443 444 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 445 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_TDPLL_BINDINGS, 446 payload, PTP_MGMTMSG_PAYLOAD_TDPLL_BINDINGS_SIZE_OCTETS, 447 resp, &resp_len))) { 448 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 449 return rv; 450 } 451 #endif 452 453 return BCM_E_NONE; 454 } 455 456 /* 457 * Function: 458 * bcm_tdpll_dpll_reference_get() 459 * Purpose: 460 * Get reference clocks for DPLL instances. 461 * Parameters: 462 * unit - (IN) Unit number. 463 * stack_id - (IN) Stack identifier index. 464 * max_num_dpll - (IN) Maximum number of DPLL instances. 465 * dpll_ref - (OUT) DPLL instance reference clocks. 466 * num_dpll - (OUT) Number of DPLL instances. 467 * Returns: 468 * BCM_E_XXX - Function status. 469 * Notes: 470 * Reference switching. Gets current reference clocks of DPLL instances. 471 */ 472 int 473 bcm_common_tdpll_dpll_reference_get( 474 int unit, 475 int stack_id, 476 int max_num_dpll, 477 int *dpll_ref, 478 int *num_dpll) 479 { 480 int rv; 481 int i; 482 int el; 483 484 uint8 resp[PTP_MGMTMSG_PAYLOAD_TDPLL_REFERENCE_SIZE_OCTETS] = {0}; 485 int resp_len = PTP_MGMTMSG_PAYLOAD_TDPLL_REFERENCE_SIZE_OCTETS; 486 487 bcm_ptp_port_identity_t portid; 488 489 /* Argument checking and error handling. */ 490 if (max_num_dpll < TDPLL_DPLL_INSTANCE_NUM_MAX) { 491 *num_dpll = 0; 492 return BCM_E_RESOURCE; 493 } 494 *num_dpll = TDPLL_DPLL_INSTANCE_NUM_MAX; 495 496 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 497 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 498 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 499 return rv; 500 } 501 502 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 503 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 504 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 505 return rv; 506 } 507 508 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 509 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_TDPLL_REFERENCE, 510 0, 0, resp, &resp_len))) { 511 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 512 return rv; 513 } 514 515 /* 516 * Parse response. 517 * Octet 0...5 : Custom management message key/identifier. 518 * BCM<null><null><null>. 519 * Octet 6 : Reference clock for DPLL instance 0. 520 * Octet 7 : Reference clock for DPLL instance 1. 521 * Octet 8 : Reference clock for DPLL instance 2. 522 * Octet 9 : Reference clock for DPLL instance 3. 523 * Octet 10 : Reference clock for DPLL instance 4. 524 * Octet 11 : Reference clock for DPLL instance 5. 525 * Octet 12 : Reference clock for DPLL instance 6. 526 */ 527 i = 6; 528 for (el = 0 ; el < *num_dpll; ++el) { 529 dpll_ref[el] = (int)((int8)resp[i++]); 530 /* Update host-side DPLL instance attributes. */ 531 DPLL(el).reference = dpll_ref[el]; 532 } 533 534 return BCM_E_NONE; 535 } 536 537 /* 538 * Function: 539 * bcm_tdpll_dpll_reference_set() 540 * Purpose: 541 * Set reference clocks for DPLL instances. 542 * Parameters: 543 * unit - (IN) Unit number. 544 * stack_id - (IN) Stack identifier index. 545 * num_dpll - (IN) Number of DPLL instances. 546 * dpll_ref - (IN) DPLL instance reference clocks. 547 * Returns: 548 * BCM_E_XXX - Function status. 549 * Notes: 550 * Reference switching. Sets current reference clocks of DPLL instances. 551 */ 552 int 553 bcm_tdpll_dpll_reference_set( 554 int unit, 555 int stack_id, 556 int num_dpll, 557 int *dpll_ref) 558 { 559 int rv; 560 int i; 561 int el; 562 563 uint8 payload[PTP_MGMTMSG_PAYLOAD_TDPLL_REFERENCE_SIZE_OCTETS] = {0}; 564 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 565 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 566 567 bcm_ptp_port_identity_t portid; 568 569 /* Argument checking and error handling. */ 570 if (num_dpll > TDPLL_DPLL_INSTANCE_NUM_MAX) { 571 num_dpll = TDPLL_DPLL_INSTANCE_NUM_MAX; 572 } 573 574 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 575 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 576 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 577 return rv; 578 } 579 580 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 581 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 582 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 583 return rv; 584 } 585 586 /* 587 * Make payload. 588 * Octet 0...5 : Custom management message key/identifier. 589 * BCM<null><null><null>. 590 * Octet 6 : Reference clock for DPLL instance (DPLL instance 0). 591 * Octet 7 : Reference clock for DPLL instance (DPLL instance 1). 592 * Octet 8 : Reference clock for DPLL instance (DPLL instance 2). 593 * Octet 9 : Reference clock for DPLL instance (DPLL instance 3). 594 * Octet 10 : Reference clock for DPLL instance 4. 595 * Octet 11 : Reference clock for DPLL instance 5. 596 * Octet 12 : Reference clock for DPLL instance 6. 597 */ 598 sal_memcpy(payload, "BCM\0\0\0", 6); 599 i = 6; 600 for (el = 0 ; el < num_dpll; ++el) { 601 payload[i++] = (uint8)dpll_ref[el]; 602 } 603 604 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 605 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_TDPLL_REFERENCE, 606 payload, PTP_MGMTMSG_PAYLOAD_TDPLL_REFERENCE_SIZE_OCTETS, 607 resp, &resp_len))) { 608 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 609 return rv; 610 } 611 612 /* Update host-side DPLL instance attributes. */ 613 for (el = 0; el < num_dpll; ++el) { 614 DPLL(el).reference = dpll_ref[el]; 615 } 616 617 return BCM_E_NONE; 618 } 619 620 /* 621 * Function: 622 * bcm_tdpll_dpll_bandwidth_get() 623 * Purpose: 624 * Get DPLL bandwidth. 625 * Parameters: 626 * unit - (IN) Unit number. 627 * stack_id - (IN) Stack identifier index. 628 * dpll_index - (IN) DPLL instance number. 629 * bandwidth - (OUT) DPLL bandwidth. 630 * Returns: 631 * BCM_E_XXX - Function status. 632 * Notes: 633 */ 634 int 635 bcm_common_tdpll_dpll_bandwidth_get( 636 int unit, 637 int stack_id, 638 int dpll_index, 639 bcm_tdpll_dpll_bandwidth_t *bandwidth) 640 { 641 int i; 642 int rv; 643 644 uint8 payload[PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS] = {0}; 645 uint8 resp[PTP_MGMTMSG_PAYLOAD_TDPLL_BANDWIDTH_SIZE_OCTETS] = {0}; 646 int resp_len = PTP_MGMTMSG_PAYLOAD_TDPLL_BANDWIDTH_SIZE_OCTETS; 647 648 bcm_ptp_port_identity_t portid; 649 650 if (dpll_index < 0 || dpll_index >= TDPLL_DPLL_INSTANCE_NUM_MAX) { 651 return BCM_E_PARAM; 652 } 653 654 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 655 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 656 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 657 return rv; 658 } 659 660 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 661 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 662 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 663 return rv; 664 } 665 666 /* Make indexed payload to get DPLL bandwidth for specified DPLL instance. */ 667 sal_memcpy(payload, "BCM\0\0\0", 6); 668 payload[6] = (uint8)dpll_index; 669 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 670 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_TDPLL_BANDWIDTH, 671 payload, PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS, 672 resp, &resp_len))) { 673 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 674 return rv; 675 } 676 677 /* 678 * Parse response. 679 * Octet 0...5 : Custom management message key/identifier. 680 * BCM<null><null><null>. 681 * Octet 6 : DPLL instance number. 682 * Octet 7...10 : DPLL bandwidth value. 683 * Octet 11 : DPLL bandwidth units. 684 */ 685 i = 6; /* Advance cursor past custom management message identifier. */ 686 ++i; /* Advance past DPLL instance number. */ 687 688 bandwidth->value = _bcm_ptp_uint32_read(resp+i); 689 i += 4; 690 bandwidth->units = (bcm_tdpll_dpll_bandwidth_units_t)resp[i]; 691 692 /* Set host-maintained DPLL instance properties. */ 693 DPLL(dpll_index).properties.bandwidth = *bandwidth; 694 695 return BCM_E_NONE; 696 } 697 698 /* 699 * Function: 700 * bcm_tdpll_dpll_bandwidth_set() 701 * Purpose: 702 * Set DPLL bandwidth. 703 * Parameters: 704 * unit - (IN) Unit number. 705 * stack_id - (IN) Stack identifier index. 706 * dpll_index - (IN) DPLL instance number. 707 * bandwidth - (IN) DPLL bandwidth. 708 * Returns: 709 * BCM_E_XXX - Function status. 710 * Notes: 711 */ 712 int 713 bcm_common_tdpll_dpll_bandwidth_set( 714 int unit, 715 int stack_id, 716 int dpll_index, 717 bcm_tdpll_dpll_bandwidth_t *bandwidth) 718 { 719 int i; 720 int rv; 721 722 uint8 payload[PTP_MGMTMSG_PAYLOAD_TDPLL_BANDWIDTH_SIZE_OCTETS] = {0}; 723 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 724 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 725 726 bcm_ptp_port_identity_t portid; 727 728 if (dpll_index < 0 || dpll_index >= TDPLL_DPLL_INSTANCE_NUM_MAX) { 729 return BCM_E_PARAM; 730 } 731 732 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 733 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 734 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 735 return rv; 736 } 737 738 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 739 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 740 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 741 return rv; 742 } 743 744 /* 745 * Make payload. 746 * Octet 0...5 : Custom management message key/identifier. 747 * BCM<null><null><null>. 748 * Octet 6 : DPLL instance number. 749 * Octet 7...10 : DPLL bandwidth value. 750 * Octet 11 : DPLL bandwidth units. 751 */ 752 sal_memcpy(payload, "BCM\0\0\0", 6); 753 i = 6; 754 payload[i++] = (uint8)dpll_index; 755 _bcm_ptp_uint32_write(payload+i, (uint32)bandwidth->value); 756 i += 4; 757 payload[i++] = (uint8)bandwidth->units; 758 759 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 760 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_TDPLL_BANDWIDTH, 761 payload, PTP_MGMTMSG_PAYLOAD_TDPLL_BANDWIDTH_SIZE_OCTETS, 762 resp, &resp_len))) { 763 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 764 return rv; 765 } 766 767 /* Set host-maintained DPLL instance properties. */ 768 DPLL(dpll_index).properties.bandwidth = *bandwidth; 769 770 return BCM_E_NONE; 771 } 772 773 /* 774 * Function: 775 * bcm_tdpll_dpll_phase_control_get() 776 * Purpose: 777 * Get DPLL instance's phase control configuration. 778 * Parameters: 779 * unit - (IN) Unit number. 780 * stack_id - (IN) Stack identifier index. 781 * dpll_index - (IN) DPLL instance number. 782 * phase_control - (OUT) Phase control configuration. 783 * Returns: 784 * BCM_E_XXX - Function status. 785 * Notes: 786 */ 787 int 788 bcm_common_tdpll_dpll_phase_control_get( 789 int unit, 790 int stack_id, 791 int dpll_index, 792 bcm_tdpll_dpll_phase_control_t *phase_control) 793 { 794 int i; 795 int rv; 796 797 uint8 payload[PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS] = {0}; 798 uint8 resp[PTP_MGMTMSG_PAYLOAD_TDPLL_PHASE_CONTROL_SIZE_OCTETS] = {0}; 799 int resp_len = PTP_MGMTMSG_PAYLOAD_TDPLL_PHASE_CONTROL_SIZE_OCTETS; 800 801 bcm_ptp_port_identity_t portid; 802 803 if (dpll_index < 0 || dpll_index >= TDPLL_DPLL_INSTANCE_NUM_MAX) { 804 return BCM_E_PARAM; 805 } 806 807 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 808 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 809 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 810 return rv; 811 } 812 813 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 814 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 815 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 816 return rv; 817 } 818 819 /* Make indexed payload to get phase control configuration for specified DPLL instance. */ 820 sal_memcpy(payload, "BCM\0\0\0", 6); 821 payload[6] = (uint8)dpll_index; 822 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 823 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_TDPLL_PHASE_CONTROL, 824 payload, PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS, 825 resp, &resp_len))) { 826 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 827 return rv; 828 } 829 830 /* 831 * Parse response. 832 * Octet 0...5 : Custom management message key/identifier. 833 * BCM<null><null><null>. 834 * Octet 6 : DPLL instance number. 835 * Octet 7 : Phase control mode. 836 * Octet 8...11 : Phase offset (ns). 837 */ 838 i = 6; /* Advance cursor past custom management message identifier. */ 839 ++i; /* Advance past DPLL instance number. */ 840 841 phase_control->mode = (bcm_tdpll_dpll_phase_mode_t)resp[i++]; 842 phase_control->offset_ns = (int32)_bcm_ptp_uint32_read(resp+i); 843 844 /* Set host-maintained DPLL instance properties. */ 845 DPLL(dpll_index).properties.phase_control = *phase_control; 846 847 return BCM_E_NONE; 848 } 849 850 /* 851 * Function: 852 * bcm_tdpll_dpll_phase_control_set() 853 * Purpose: 854 * Set DPLL instance's phase control configuration. 855 * Parameters: 856 * unit - (IN) Unit number. 857 * stack_id - (IN) Stack identifier index. 858 * dpll_index - (IN) DPLL instance number. 859 * phase_control - (IN) Phase control configuration. 860 * Returns: 861 * BCM_E_XXX - Function status. 862 * Notes: 863 */ 864 int 865 bcm_common_tdpll_dpll_phase_control_set( 866 int unit, 867 int stack_id, 868 int dpll_index, 869 bcm_tdpll_dpll_phase_control_t *phase_control) 870 { 871 int i; 872 int rv; 873 874 uint8 payload[PTP_MGMTMSG_PAYLOAD_TDPLL_PHASE_CONTROL_SIZE_OCTETS] = {0}; 875 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 876 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 877 878 bcm_ptp_port_identity_t portid; 879 880 if (dpll_index < 0 || dpll_index >= TDPLL_DPLL_INSTANCE_NUM_MAX) { 881 return BCM_E_PARAM; 882 } 883 884 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 885 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 886 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 887 return rv; 888 } 889 890 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 891 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 892 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 893 return rv; 894 } 895 896 /* 897 * Make payload. 898 * Octet 0...5 : Custom management message key/identifier. 899 * BCM<null><null><null>. 900 * Octet 6 : DPLL instance number. 901 * Octet 7 : Phase control mode. 902 * Octet 8...11 : Phase offset (ns). 903 */ 904 sal_memcpy(payload, "BCM\0\0\0", 6); 905 i = 6; 906 payload[i++] = (uint8)dpll_index; 907 payload[i++] = (uint8)phase_control->mode; 908 909 _bcm_ptp_uint32_write(payload+i, (uint32)phase_control->offset_ns); 910 911 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 912 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_TDPLL_PHASE_CONTROL, 913 payload, PTP_MGMTMSG_PAYLOAD_TDPLL_PHASE_CONTROL_SIZE_OCTETS, 914 resp, &resp_len))) { 915 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 916 return rv; 917 } 918 919 /* Set host-maintained DPLL instance properties. */ 920 DPLL(dpll_index).properties.phase_control = *phase_control; 921 922 return BCM_E_NONE; 923 } 924 925 #if defined(BCM_MONTEREY_SUPPORT) 926 /* 927 * Function: 928 * _bcm_common_tdpll_dpll_binding_lookup() 929 * Purpose: 930 * Get DPLL instance number associated with output clock/synthesizer. 931 * Parameters: 932 * clock_index - (IN) Output clock number. 933 * dpll_index - (OUT) DPLL instance number. 934 * Returns: 935 * None. 936 * Notes: 937 * A negative answer (DPLL index) signifies that the synthesizer is not 938 * bound to any logical DPLL instances. 939 * 940 * ASSUMPTION(s) - Host code guarantees that a synthesizer is bound to 941 * only one DPLL instance. Design allows N-to-1 mappings, i.e. multiple 942 * synthesizers to one DPLL, but does not permit 1-to-N mappings, i.e. 943 * one synthesizer to multiple DPLLs. 944 */ 945 int _bcm_common_tdpll_dpll_outclock_binding_lookup(int clock_index, int *dpll_index) 946 { 947 int i; 948 *dpll_index = -1; 949 950 /* Argument checking and error handling. */ 951 if (clock_index < 0 || clock_index >= TDPLL_OUTPUT_CLOCK_NUM_MAX) { 952 return BCM_E_PARAM; 953 } 954 955 for (i = 0; i < TDPLL_DPLL_INSTANCE_NUM_MAX; ++i) { 956 #if defined(BCM_MONTEREY_SUPPORT) 957 if (DPLL(i).bindings.output_clocks[i/SHR_BITWID] & (1 << (clock_index % SHR_BITWID))) { 958 #else 959 if (DPLL(i).bindings.output_clocks & (1 << clock_index)) { 960 #endif 961 /* Synthesizer is bound to this DPLL. */ 962 *dpll_index = i; 963 break; 964 } 965 } 966 967 return BCM_E_NONE; 968 } 969 970 int _bcm_common_tdpll_dpll_outclock_bandwidth_get(int clock_index, bcm_tdpll_dpll_bandwidth_t *bandwidth) 971 { 972 int dpll_index = -1; 973 int rv = BCM_E_UNAVAIL; 974 bandwidth->value = -1; 975 976 if (BCM_FAILURE(rv = _bcm_common_tdpll_dpll_outclock_binding_lookup(clock_index, &dpll_index))) { 977 PTP_ERROR_FUNC("_bcm_common_tdpll_dpll_outclock_binding_lookup()"); 978 return rv; 979 } 980 981 *bandwidth = DPLL(dpll_index).properties.bandwidth; 982 return BCM_E_NONE; 983 } 984 #endif /* BCM_MONTEREY_SUPPORT */ 985 986 #endif /* defined(INCLUDE_PTP) */