tdpll_outputs.c (53084B)
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_outputs.c 8 * 9 * Purpose: Telecom DPLL output clock (synthesizer) configuration and management. 10 * 11 * Functions: 12 * bcm_tdpll_output_clock_init 13 * bcm_tdpll_output_clock_enable_get 14 * bcm_tdpll_output_clock_enable_set 15 * bcm_tdpll_output_clock_synth_frequency_get 16 * bcm_tdpll_output_clock_synth_frequency_set 17 * bcm_tdpll_output_clock_deriv_frequency_get 18 * bcm_tdpll_output_clock_deriv_frequency_set 19 * bcm_tdpll_output_clock_holdover_data_get 20 * bcm_tdpll_output_clock_holdover_frequency_set 21 * bcm_tdpll_output_clock_holdover_mode_get 22 * bcm_tdpll_output_clock_holdover_mode_set 23 * bcm_tdpll_output_clock_holdover_reset 24 */ 25 26 #if defined(INCLUDE_PTP) 27 28 #include <shared/bsl.h> 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 #if defined(BCM_MONTEREY_SUPPORT) & defined(INCLUDE_GDPLL) 36 #include <bcm/gdpll.h> 37 #endif 38 39 /* Definitions. */ 40 #define TDPLL_OUTPUT_CLOCK_STATE_ENABLE_BIT (0u) 41 42 #define OUTPUT_CLOCK(clock_index) \ 43 (objdata.output_clock[clock_index]) 44 45 /* Macros. */ 46 47 /* Types. */ 48 49 /* Constants and variables. */ 50 static bcm_tdpll_output_clock_data_t objdata; 51 52 /* Static functions. */ 53 #if defined(BCM_MONTEREY_SUPPORT) 54 #define OUTCLOCK_BS (1) 55 #define OUTCLOCK_SYNCE (2) 56 #define OUTCLOCK_1588 (3) 57 #define OUTCLOCK_GPIO (4) 58 59 typedef struct tdpllout_gdpll_state_s { 60 uint32 outClk_gdpllChan[TDPLL_OUTPUT_CLOCK_NUM_MAX]; /* Hold the I/A indicator of each instance */ 61 uint32 outClk_port[TDPLL_OUTPUT_CLOCK_NUM_MAX]; 62 } tdpllout_gdpll_state_t; 63 64 tdpllout_gdpll_state_t tdpllout_gdpll_state; 65 66 uint32 gdpll_txpi_coeff_table[8][8] = { 67 /* Stage 0 Stage 1 68 * K1, K1Shift, K1K2, K1K2Shift, K1, K1Shift, K1K2, K1K2Shift */ 69 {720575940, 14, 737869763, 8, 910032812, 5, 15540, 2}, /* 0.01 Hz */ 70 {720575940, 14, 737869763, 8, 568770507, 8, 12140, 7}, /* 0.05 Hz */ 71 {688285981, 14, 831137788, 8, 568770507, 9, 3107903, 1}, /* 0.1 Hz */ 72 {720575940, 14, 737869763, 8, 710963134, 11, 2428049, 6}, /* 0.5 Hz */ 73 {720575940, 14, 737869763, 8, 710963134, 12, 621580576, 0}, /* 1 Hz */ 74 {688285981, 14, 831137788, 8, 710963134, 14, 621580576, 4}, /* 4 Hz */ 75 {720575940, 14, 737869763, 8, 888703918, 14, 971219650, 4}, /* 5 Hz */ 76 {720575940, 15, 737869763, 10, 888703918, 15, 971219650, 6} /* 10 Hz */ 77 }; 78 79 uint32 gdpll_ts_counter_coeff_table[8][8] = { 80 /* Stage 0 Stage 1 81 * K1, K1Shift, K1K2, K1K2Shift, K1, K1Shift, K1K2, K1K2Shift */ 82 {576460752, 2, 2305843, 4, 0,0, 0,0}, /* 0.01 Hz */ 83 {576460752, 2, 2305843, 4, 0,0, 0,0}, /* 0.05 Hz */ 84 {3441430, 9, 3324551, 3, 2221760, 10, 15175, 7}, /* 0.1 Hz */ 85 {576460752, 2, 2305843, 4, 2221760, 7, 15175, 1}, /* 0.5 Hz */ 86 {3441430, 9, 3324551, 3, 2221760, 10, 15175, 7}, /* 1 Hz */ 87 {3441430, 9, 3324551, 3, 2221760, 10, 15175, 7}, /* 4 Hz */ 88 {576460752, 2, 2305843, 4, 710963134, 2, 3035061, 0}, /* 5 Hz */ 89 {576460752, 3, 2305843, 6, 710963134, 3, 3035061, 2} /* 10 Hz */ 90 }; 91 92 #define OUTPUT_CLOCK_GDPLLCHAN(clock_index) \ 93 (tdpllout_gdpll_state.outClk_gdpllChan[clock_index]) 94 95 int _bcm_esw_tdpllOutinstance_bind(int unit, int outclock_index, uint32 tdpll_instance_num); 96 extern int _bcm_esw_gdpll_tdpllinstance_bind(int unit, int gdpllChan, uint32 tdpll_instance_num); 97 extern int _bcm_common_tdpll_dpll_outclock_bandwidth_get(int clock_index, bcm_tdpll_dpll_bandwidth_t *bandwidth); 98 #endif 99 100 101 #if defined(BCM_MONTEREY_SUPPORT) & defined(INCLUDE_GDPLL) 102 int _bcm_esw_tdpllOutinstance_bind(int unit, int outclock_index, uint32 tdpll_instance_num) 103 { 104 int rv = BCM_E_NONE; 105 106 cli_out("### _bcm_esw_tdpllOutinstance_bind: outclock_index:%d, chan:%d, instance:%d\n", 107 outclock_index, OUTPUT_CLOCK_GDPLLCHAN(outclock_index), tdpll_instance_num); 108 109 rv = _bcm_esw_gdpll_tdpllinstance_bind(unit, OUTPUT_CLOCK_GDPLLCHAN(outclock_index), tdpll_instance_num); 110 return rv; 111 } 112 113 int _bcm_esw_tdpll_outClk_portSet(int unit, int outclock_index, uint32 port) 114 { 115 int rv = BCM_E_NONE; 116 tdpllout_gdpll_state.outClk_port[outclock_index] = port; 117 118 return rv; 119 } 120 121 void gdpll_chan_bandwidth_dependent_config(bcm_gdpll_chan_t *pGdpllChan, int outClock, bcm_tdpll_dpll_bandwidth_t bw) 122 { 123 uint8 bw_index = 255; 124 125 /* Stage 0 */ 126 pGdpllChan->chan_dpll_config.k1[0] = 0; 127 pGdpllChan->chan_dpll_config.k1Shift[0] = 0; 128 pGdpllChan->chan_dpll_config.k1k2[0] = 0; 129 pGdpllChan->chan_dpll_config.k1Shift[0] = 0; 130 131 /* Stage 1 */ 132 pGdpllChan->chan_dpll_config.k1[1] = 0; 133 pGdpllChan->chan_dpll_config.k1Shift[1] = 0; 134 pGdpllChan->chan_dpll_config.k1k2[1] = 0; 135 pGdpllChan->chan_dpll_config.k1Shift[1] = 0; 136 137 /* Stage 2 */ 138 pGdpllChan->chan_dpll_config.k1[2] = 0; 139 pGdpllChan->chan_dpll_config.k1Shift[2] = 0; 140 pGdpllChan->chan_dpll_config.k1k2[2] = 0; 141 pGdpllChan->chan_dpll_config.k1Shift[2] = 0; 142 143 144 switch (bw.units) { 145 case bcm_tdpll_dpll_bandwidth_mHz: 146 switch (bw.value) { 147 case 10: 148 /* 0.01 Hz. */ 149 bw_index = 0; 150 break; 151 case 50: 152 /* 0.05 Hz. */ 153 bw_index = 1; 154 break; 155 case 100: 156 /* 0.10 Hz. */ 157 bw_index = 2; 158 break; 159 case 500: 160 /* 0.50 Hz. */ 161 bw_index = 3; 162 break; 163 default: 164 break; 165 } 166 break; 167 case bcm_tdpll_dpll_bandwidth_Hz: 168 switch (bw.value) { 169 case 1: 170 /* 1 Hz. */ 171 bw_index = 4; 172 break; 173 case 4: 174 /* 1 Hz. */ 175 bw_index = 5; 176 break; 177 case 5: 178 /* 5 Hz. */ 179 bw_index = 6; 180 break; 181 case 10: 182 /* 10 Hz. */ 183 bw_index = 7; 184 break; 185 default: 186 break; 187 } 188 break; 189 case bcm_tdpll_dpll_bandwidth_kHz: 190 /* Fall through. */ 191 default: 192 break; 193 } 194 if (bw_index > 7){ 195 cli_out("Error setting bandwidth dependent parameters: gdpll_chan_bandwidth_dependent_config()!!!\n"); 196 return; 197 } 198 199 cli_out("bw_index = %d\n", bw_index); 200 if (outClock == OUTCLOCK_SYNCE) { 201 /* Stage 0 */ 202 pGdpllChan->chan_dpll_config.k1[0] = gdpll_txpi_coeff_table[bw_index][0]; 203 pGdpllChan->chan_dpll_config.k1Shift[0] = gdpll_txpi_coeff_table[bw_index][1]; 204 pGdpllChan->chan_dpll_config.k1k2[0] = gdpll_txpi_coeff_table[bw_index][2]; 205 pGdpllChan->chan_dpll_config.k1k2Shift[0] = gdpll_txpi_coeff_table[bw_index][3]; 206 207 /* Stage 1 */ 208 pGdpllChan->chan_dpll_config.k1[1] = gdpll_txpi_coeff_table[bw_index][4]; 209 pGdpllChan->chan_dpll_config.k1Shift[1] = gdpll_txpi_coeff_table[bw_index][5]; 210 pGdpllChan->chan_dpll_config.k1k2[1] = gdpll_txpi_coeff_table[bw_index][6]; 211 pGdpllChan->chan_dpll_config.k1k2Shift[1] = gdpll_txpi_coeff_table[bw_index][7]; 212 } else if ((outClock == OUTCLOCK_1588)){ 213 /* Stage 0 */ 214 pGdpllChan->chan_dpll_config.k1[0] = gdpll_ts_counter_coeff_table[bw_index][0]; 215 pGdpllChan->chan_dpll_config.k1Shift[0] = gdpll_ts_counter_coeff_table[bw_index][1]; 216 pGdpllChan->chan_dpll_config.k1k2[0] = gdpll_ts_counter_coeff_table[bw_index][2]; 217 pGdpllChan->chan_dpll_config.k1k2Shift[0] = gdpll_ts_counter_coeff_table[bw_index][3]; 218 219 /* Stage 1 */ 220 pGdpllChan->chan_dpll_config.k1[1] = gdpll_ts_counter_coeff_table[bw_index][4]; 221 pGdpllChan->chan_dpll_config.k1Shift[1] = gdpll_ts_counter_coeff_table[bw_index][5]; 222 pGdpllChan->chan_dpll_config.k1k2[1] = gdpll_ts_counter_coeff_table[bw_index][6]; 223 pGdpllChan->chan_dpll_config.k1k2Shift[1] = gdpll_ts_counter_coeff_table[bw_index][7]; 224 } 225 226 227 cli_out("k1[0]: %d, k1Shift[0]: %d, k1k2[0]: %d, k1k2Shift[0]: %d\n", 228 pGdpllChan->chan_dpll_config.k1[0], pGdpllChan->chan_dpll_config.k1Shift[0], 229 pGdpllChan->chan_dpll_config.k1k2[0], pGdpllChan->chan_dpll_config.k1k2Shift[0]); 230 231 cli_out("k1[1]: %d, k1Shift[1]: %d, k1k2[1]: %d, k1k2Shift[1]: %d\n", 232 pGdpllChan->chan_dpll_config.k1[1], pGdpllChan->chan_dpll_config.k1Shift[1], 233 pGdpllChan->chan_dpll_config.k1k2[1], pGdpllChan->chan_dpll_config.k1k2Shift[1]); 234 235 cli_out("k1[2]: %d, k1Shift[2]: %d, k1k2[2]: %d, k1k2Shift[2]: %d\n", 236 pGdpllChan->chan_dpll_config.k1[2], pGdpllChan->chan_dpll_config.k1Shift[2], 237 pGdpllChan->chan_dpll_config.k1k2[2], pGdpllChan->chan_dpll_config.k1k2Shift[2]); 238 239 } 240 void gdpll_chan_config(int unit, bcm_gdpll_chan_t *pGdpllChan, int outClock, bcm_tdpll_dpll_bandwidth_t bw) 241 { 242 gdpll_chan_bandwidth_dependent_config(pGdpllChan, outClock, bw); 243 if (outClock == OUTCLOCK_SYNCE) { 244 245 pGdpllChan->chan_dpll_config.lockDetThres[0]=25600; 246 pGdpllChan->chan_dpll_config.lockDetThres[1]=80000; 247 pGdpllChan->chan_dpll_config.lockDetThres[2]=0; 248 249 pGdpllChan->chan_dpll_config.dwell_count[0]=1000; 250 pGdpllChan->chan_dpll_config.dwell_count[1]=1000; 251 pGdpllChan->chan_dpll_config.dwell_count[2]=0; 252 u64_H(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[0])=0; 253 u64_L(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[0])=200000; 254 u64_H(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[1])=0; 255 u64_L(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[1])=195000; 256 u64_H(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[2])=0; 257 u64_L(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[2])=0; 258 259 pGdpllChan->chan_dpll_config.nco_bits=48; 260 pGdpllChan->chan_dpll_config.dpll_num_states=2; 261 262 pGdpllChan->chan_dpll_config.idump_mod[0]=0; 263 pGdpllChan->chan_dpll_config.idump_mod[1]=0; 264 pGdpllChan->chan_dpll_config.idump_mod[2]=0; 265 266 pGdpllChan->chan_dpll_config.phase_error_shift=12; 267 u64_H(pGdpllChan->chan_dpll_config.nominal_loop_filter)=0; 268 u64_L(pGdpllChan->chan_dpll_config.nominal_loop_filter)=0; 269 pGdpllChan->chan_dpll_config.invert_phase_error=0; 270 pGdpllChan->chan_dpll_config.lockIndicatorThresholdLHi=80000; 271 pGdpllChan->chan_dpll_config.lockIndicatorThresholdLo=25600; 272 pGdpllChan->chan_dpll_config.norm_phase_error=1; 273 pGdpllChan->chan_dpll_config.norm_phase_error_thres0=16000000; 274 pGdpllChan->chan_dpll_config.norm_phase_error_thres1=8100; 275 276 /* DPLL State */ 277 pGdpllChan->chan_dpll_state.dpll_state=0; 278 u64_H(pGdpllChan->chan_dpll_state.loop_filter)=0; 279 u64_L(pGdpllChan->chan_dpll_state.loop_filter)=0; 280 pGdpllChan->chan_dpll_state.dwell_counter=1000; 281 pGdpllChan->chan_dpll_state.lockDetFilter=120000; 282 u64_H(pGdpllChan->chan_dpll_state.offset)=0; 283 u64_L(pGdpllChan->chan_dpll_state.offset)=0; 284 pGdpllChan->chan_dpll_state.init_flag=0; 285 pGdpllChan->chan_dpll_state.init_offset_flag=1; 286 u64_H(pGdpllChan->chan_dpll_state.phase_counter)=0; 287 u64_L(pGdpllChan->chan_dpll_state.phase_counter)=0; 288 u64_H(pGdpllChan->chan_dpll_state.phaseCounterDelta)=0; 289 u64_L(pGdpllChan->chan_dpll_state.phaseCounterDelta)=0; 290 pGdpllChan->chan_dpll_state.phaseCounterM=0; 291 pGdpllChan->chan_dpll_state.phaseCounterN=1; 292 pGdpllChan->chan_dpll_state.phaseCounterFrac=0; 293 pGdpllChan->chan_dpll_state.idumpCounter=0; 294 u64_H(pGdpllChan->chan_dpll_state.accumPhaseError)=0; 295 u64_L(pGdpllChan->chan_dpll_state.accumPhaseError)=0; 296 297 } else if (outClock == OUTCLOCK_1588) { 298 /* DPLL configs */ 299 pGdpllChan->chan_dpll_config.lockDetThres[0]=25600; 300 pGdpllChan->chan_dpll_config.lockDetThres[1]=80000; 301 pGdpllChan->chan_dpll_config.lockDetThres[2]=0; 302 303 pGdpllChan->chan_dpll_config.dwell_count[0]=500; 304 pGdpllChan->chan_dpll_config.dwell_count[1]=500; 305 pGdpllChan->chan_dpll_config.dwell_count[2]=0; 306 u64_H(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[0])=0; 307 u64_L(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[0])=100000000; 308 u64_H(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[1])=0; 309 u64_L(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[1])=100000000; 310 u64_H(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[2])=0; 311 u64_L(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[2])=0; 312 313 pGdpllChan->chan_dpll_config.nco_bits=48; 314 pGdpllChan->chan_dpll_config.dpll_num_states=2; 315 316 pGdpllChan->chan_dpll_config.idump_mod[0]=0; 317 pGdpllChan->chan_dpll_config.idump_mod[1]=0; 318 pGdpllChan->chan_dpll_config.idump_mod[2]=0; 319 320 pGdpllChan->chan_dpll_config.phase_error_shift=12; 321 u64_H(pGdpllChan->chan_dpll_config.nominal_loop_filter)=0x20000000; 322 u64_L(pGdpllChan->chan_dpll_config.nominal_loop_filter)=0; 323 pGdpllChan->chan_dpll_config.invert_phase_error=0; 324 pGdpllChan->chan_dpll_config.lockIndicatorThresholdLHi=80000; 325 pGdpllChan->chan_dpll_config.lockIndicatorThresholdLo=25600; 326 pGdpllChan->chan_dpll_config.norm_phase_error=0; 327 pGdpllChan->chan_dpll_config.norm_phase_error_thres0=1600000000; 328 pGdpllChan->chan_dpll_config.norm_phase_error_thres1=1600000000; 329 330 /* DPLL State */ 331 pGdpllChan->chan_dpll_state.dpll_state=0; 332 u64_H(pGdpllChan->chan_dpll_state.loop_filter)=0x20000000; 333 u64_L(pGdpllChan->chan_dpll_state.loop_filter)=0; 334 pGdpllChan->chan_dpll_state.dwell_counter=500; 335 pGdpllChan->chan_dpll_state.lockDetFilter=120000; 336 u64_H(pGdpllChan->chan_dpll_state.offset)=0; 337 u64_L(pGdpllChan->chan_dpll_state.offset)=0; 338 pGdpllChan->chan_dpll_state.init_flag=1; 339 pGdpllChan->chan_dpll_state.init_offset_flag=0; 340 u64_H(pGdpllChan->chan_dpll_state.phase_counter)=0; 341 u64_L(pGdpllChan->chan_dpll_state.phase_counter)=0; 342 u64_H(pGdpllChan->chan_dpll_state.phaseCounterDelta)=0; 343 u64_L(pGdpllChan->chan_dpll_state.phaseCounterDelta)=64000000; 344 pGdpllChan->chan_dpll_state.phaseCounterM=0; 345 pGdpllChan->chan_dpll_state.phaseCounterN=1; 346 pGdpllChan->chan_dpll_state.phaseCounterFrac=0; 347 pGdpllChan->chan_dpll_state.idumpCounter=0; 348 u64_H(pGdpllChan->chan_dpll_state.accumPhaseError)=0; 349 u64_L(pGdpllChan->chan_dpll_state.accumPhaseError)=0; 350 } 351 352 return; 353 } 354 #endif 355 356 /* 357 * Function: 358 * bcm_tdpll_output_clock_init() 359 * Purpose: 360 * Initialize T-DPLL output clock configuration and management data. 361 * Parameters: 362 * unit - (IN) Unit number. 363 * stack_id - (IN) Stack identifier index. 364 * Returns: 365 * BCM_E_XXX - Function status. 366 * Notes: 367 */ 368 int 369 bcm_tdpll_output_clock_init( 370 int unit, 371 int stack_id) 372 { 373 int i; 374 375 /*Initialize output clock attributes. */ 376 for (i = 0; i < TDPLL_OUTPUT_CLOCK_NUM_MAX; ++i) { 377 /* Identification attributes. */ 378 OUTPUT_CLOCK(i).index = i; 379 380 /* Synthesizer frequency and TS EVENT (timestamp) frequency. */ 381 OUTPUT_CLOCK(i).frequency.synth = 0; 382 OUTPUT_CLOCK(i).frequency.tsevent = 0; 383 OUTPUT_CLOCK(i).frequency.tsevent_quotient = -1; 384 385 /* Derivative clock frequency. */ 386 OUTPUT_CLOCK(i).frequency.deriv = 0; 387 OUTPUT_CLOCK(i).frequency.deriv_quotient = -1; 388 389 /* State. */ 390 OUTPUT_CLOCK(i).state = 0; 391 #if defined(BCM_MONTEREY_SUPPORT) 392 OUTPUT_CLOCK_GDPLLCHAN(i) = -1; 393 tdpllout_gdpll_state.outClk_port[i] = -1; 394 #endif 395 } 396 397 return BCM_E_NONE; 398 } 399 400 /* 401 * Function: 402 * bcm_tdpll_output_clock_cleanup() 403 * Purpose: 404 * Uninitialize T-DPLL output clock configuration and management data. 405 * Parameters: 406 * unit - (IN) Unit number. 407 * stack_id - (IN) Stack identifier index. 408 * Returns: 409 * BCM_E_XXX - Function status. 410 * Notes: 411 */ 412 int 413 bcm_tdpll_output_clock_cleanup( 414 int unit, 415 int stack_id) 416 { 417 return BCM_E_NONE; 418 } 419 420 /* 421 * Function: 422 * _bcm_common_tdpll_output_clock_index_validate() 423 * Purpose: 424 * Validate the TDPLL output clock index. 425 * Parameters: 426 * unit - (IN) Unit number. 427 * clock_index - (IN) Output clock index. 428 * Returns: 429 * BCM_E_XXX - Function status. 430 * Notes: 431 */ 432 433 static int 434 _bcm_common_tdpll_output_clock_index_validate ( 435 int unit, 436 int clock_index) 437 { 438 int rv = BCM_E_NONE; 439 440 if (clock_index < 0 || clock_index >= TDPLL_OUTPUT_CLOCK_NUM_MAX) { 441 return BCM_E_PARAM; 442 } 443 444 if (!soc_feature(unit, soc_feature_tdpll_outputclk_synce3) && 445 (clock_index == TDPLL_OUTPUT_CLOCK_IDX_SYNCE3) ) { 446 return BCM_E_PARAM; 447 } 448 449 if (!soc_feature(unit, soc_feature_tdpll_outputclk_xgpll3) && 450 (clock_index == TDPLL_OUTPUT_CLOCK_IDX_XGPLL3)) { 451 return BCM_E_PARAM; 452 } 453 454 #if defined (BCM_QAX_SUPPORT) 455 if ((SOC_IS_QUX(unit) || SOC_IS_QAX(unit)) && 456 ((clock_index == TDPLL_OUTPUT_CLOCK_IDX_GPIO4) || 457 (clock_index == TDPLL_OUTPUT_CLOCK_IDX_GPIO5)) ) { 458 return BCM_E_PARAM; 459 } 460 #endif 461 return rv; 462 } 463 464 /* 465 * Function: 466 * bcm_tdpll_output_clock_enable_get() 467 * Purpose: 468 * Get output clock enable Boolean. 469 * Parameters: 470 * unit - (IN) Unit number. 471 * stack_id - (IN) Stack identifier index. 472 * clock_index - (IN) Output clock index. 473 * enable - (OUT) Output clock enable Boolean. 474 * Returns: 475 * BCM_E_XXX - Function status. 476 * Notes: 477 */ 478 int 479 bcm_common_tdpll_output_clock_enable_get( 480 int unit, 481 int stack_id, 482 int clock_index, 483 int *enable) 484 { 485 int i; 486 int rv; 487 488 uint8 payload[PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS] = {0}; 489 uint8 resp[PTP_MGMTMSG_PAYLOAD_OUTPUT_CLOCK_ENABLED_SIZE_OCTETS] = {0}; 490 int resp_len = PTP_MGMTMSG_PAYLOAD_OUTPUT_CLOCK_ENABLED_SIZE_OCTETS; 491 492 bcm_ptp_port_identity_t portid; 493 494 if (clock_index < 0 || clock_index >= TDPLL_OUTPUT_CLOCK_NUM_MAX) { 495 return BCM_E_PARAM; 496 } 497 498 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 499 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 500 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 501 return rv; 502 } 503 504 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 505 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 506 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 507 return rv; 508 } 509 510 /* Make indexed payload to get frequency for specified output clock. */ 511 sal_memcpy(payload, "BCM\0\0\0", 6); 512 payload[6] = (uint8)clock_index; 513 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 514 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_OUTPUT_CLOCK_ENABLED, 515 payload, PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS, 516 resp, &resp_len))) { 517 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 518 return rv; 519 } 520 521 /* 522 * Parse response. 523 * Octet 0...5 : Custom management message key/identifier. 524 * BCM<null><null><null>. 525 * Octet 6 : Output clock index. 526 * Octet 7 : Output clock enable Boolean. 527 */ 528 i = 6; /* Advance cursor past custom management message identifier. */ 529 ++i; /* Advance past output clock index. */ 530 531 *enable = resp[i] ? 1:0; 532 533 /* Set host-maintained output clock enable Boolean. */ 534 if (*enable) { 535 OUTPUT_CLOCK(clock_index).state |= (1 << TDPLL_OUTPUT_CLOCK_STATE_ENABLE_BIT); 536 } else { 537 OUTPUT_CLOCK(clock_index).state &= ~(1 << TDPLL_OUTPUT_CLOCK_STATE_ENABLE_BIT); 538 } 539 540 return BCM_E_NONE; 541 } 542 543 /* 544 * Function: 545 * bcm_tdpll_output_clock_enable_set() 546 * Purpose: 547 * Set output clock enable Boolean. 548 * Parameters: 549 * unit - (IN) Unit number. 550 * stack_id - (IN) Stack identifier index. 551 * clock_index - (IN) Output clock index. 552 * enable - (IN) Output clock enable Boolean. 553 * Returns: 554 * BCM_E_XXX - Function status. 555 * Notes: 556 */ 557 int 558 bcm_common_tdpll_output_clock_enable_set( 559 int unit, 560 int stack_id, 561 int clock_index, 562 int enable) 563 { 564 int i; 565 int rv; 566 567 uint8 payload[PTP_MGMTMSG_PAYLOAD_OUTPUT_CLOCK_ENABLED_SIZE_OCTETS] = {0}; 568 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 569 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 570 571 bcm_ptp_port_identity_t portid; 572 573 #if defined(BCM_MONTEREY_SUPPORT) & defined(INCLUDE_GDPLL) 574 uint32 flags = BCM_GDPLL_CONF_DPLL | 575 BCM_GDPLL_EVENT_CONFIG_REF | BCM_GDPLL_EVENT_CONFIG_FB | 576 BCM_GDPLL_CHAN_ALLOC | BCM_GDPLL_CHAN_SET_PRIORITY | 577 BCM_GDPLL_CHAN_OUTPUT_CONF; 578 int result=0, gdpllChan=0; 579 bcm_gdpll_chan_t gdpll_chan; 580 bcm_tdpll_dpll_bandwidth_t bandwidth; 581 582 sal_memset(&gdpll_chan, 0, sizeof(bcm_gdpll_chan_t)); 583 #endif 584 585 if (BCM_FAILURE(rv = _bcm_common_tdpll_output_clock_index_validate(unit, clock_index))) { 586 PTP_ERROR_FUNC("_bcm_common_tdpll_output_clock_index_validate()"); 587 return rv; 588 } 589 590 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 591 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 592 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 593 return rv; 594 } 595 596 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 597 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 598 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 599 return rv; 600 } 601 602 #if defined(BCM_MONTEREY_SUPPORT) & defined(INCLUDE_GDPLL) 603 if (clock_index < BCM_TDPLL_OUTPUT_CLOCK_NUM_BROADSYNC) { 604 605 cli_out("### tdpll_output_clock: Set BS%d\n", clock_index); 606 607 } else if (clock_index < (BCM_TDPLL_OUTPUT_CLOCK_NUM_BROADSYNC + BCM_TDPLL_OUTPUT_CLOCK_NUM_SYNCE)) { 608 cli_out("### tdpll_output_clock: Output clock is SyncE: clock_index:%d, port:%d divisor:%d\n", 609 clock_index, tdpllout_gdpll_state.outClk_port[clock_index], 610 OUTPUT_CLOCK(clock_index).frequency.tsevent_quotient/2); 611 612 /* Feedback config */ 613 gdpll_chan.event_fb.input_event = bcmGdpllInputEventPORT; 614 gdpll_chan.event_fb.port = tdpllout_gdpll_state.outClk_port[clock_index]; 615 gdpll_chan.event_fb.port_event_type = bcmGdpllPortEventTXPI; 616 gdpll_chan.event_fb.event_divisor = OUTPUT_CLOCK(clock_index).frequency.tsevent_quotient/2; 617 gdpll_chan.event_fb.event_dest = bcmGdpllEventDestM7; 618 gdpll_chan.event_fb.ts_counter = 0; /* TS0 */ 619 620 /* Reference config */ 621 gdpll_chan.event_ref.input_event = bcmGdpllInputEventR5; 622 gdpll_chan.event_ref.event_dest = bcmGdpllEventDestCPU; 623 gdpll_chan.event_ref.event_divisor = 1; 624 625 gdpll_chan.chan_prio = 0; 626 gdpll_chan.out_event = bcmGdpllOutputEventTXPI; 627 gdpll_chan.port = gdpll_chan.event_fb.port; 628 gdpll_chan.ts_pair_dest = bcmGdpllDebugDestM7; 629 630 /* Set phase counter reference */ 631 gdpll_chan.chan_dpll_config.phase_counter_ref = 0; 632 633 if (BCM_FAILURE(rv = _bcm_common_tdpll_dpll_outclock_bandwidth_get(clock_index, &bandwidth))) { 634 PTP_ERROR_FUNC("_bcm_common_tdpll_dpll_outclock_bandwidth_get()"); 635 return rv; 636 } 637 gdpll_chan_config(unit, &gdpll_chan, OUTCLOCK_SYNCE, bandwidth); 638 639 } else if (clock_index == (BCM_TDPLL_OUTPUT_CLOCK_NUM_BROADSYNC + BCM_TDPLL_OUTPUT_CLOCK_NUM_SYNCE)) { 640 cli_out("### tdpll_output_clock_enable_set: Output clock is 1588-Hybrid\n"); 641 642 /* Reference config */ 643 gdpll_chan.event_fb.input_event = bcmGdpllInputEventR5; 644 gdpll_chan.event_fb.event_dest = bcmGdpllEventDestCPU; 645 gdpll_chan.event_fb.event_divisor = 1; 646 647 /* Channel output configurations */ 648 gdpll_chan.chan_prio = 0; 649 gdpll_chan.out_event = bcmGdpllOutputEventTS0; 650 gdpll_chan.ts_pair_dest = bcmGdpllDebugDestM7; 651 gdpll_chan.event_fb.ts_counter = 0; /* TS0 */ 652 653 /* Set phase counter reference */ 654 gdpll_chan.chan_dpll_config.phase_counter_ref = 1; 655 656 if (BCM_FAILURE(rv = _bcm_common_tdpll_dpll_outclock_bandwidth_get(clock_index, &bandwidth))) { 657 PTP_ERROR_FUNC("_bcm_common_tdpll_dpll_outclock_bandwidth_get()"); 658 return rv; 659 } 660 661 /* DPLL config for 1588 */ 662 gdpll_chan_config(unit, &gdpll_chan, OUTCLOCK_1588, bandwidth); 663 664 665 } else if (clock_index < TDPLL_OUTPUT_CLOCK_NUM_MAX) { 666 cli_out("### tdpll_output_clock_enable_set: Output clock is GPIO\n"); 667 } 668 669 result = bcm_gdpll_chan_create (unit, flags, &gdpll_chan, &gdpllChan); 670 if (BCM_FAILURE(result)) { 671 cli_out("### tdpll_output_clock_enable_set: Error!! gdpll chan create failed\n"); 672 } 673 674 if (result == BCM_E_NONE) { 675 result = bcm_gdpll_chan_enable(unit, gdpllChan, 1); 676 if (BCM_FAILURE(result)) { 677 cli_out("### tdpll_output_clock_enable_set: Error!! gdpll chan enable failed\n"); 678 return result; 679 } 680 OUTPUT_CLOCK_GDPLLCHAN(clock_index) = gdpllChan; 681 } 682 683 cli_out("### gdpll_chan:%d\n", gdpllChan); 684 #endif 685 686 /* 687 * Make payload. 688 * Octet 0...5 : Custom management message key/identifier. 689 * BCM<null><null><null>. 690 * Octet 6 : Output clock index. 691 * Octet 7 : Output clock enable Boolean. 692 */ 693 sal_memcpy(payload, "BCM\0\0\0", 6); 694 i = 6; 695 payload[i++] = (uint8)clock_index; 696 payload[i] = enable ? 1:0; 697 698 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 699 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_OUTPUT_CLOCK_ENABLED, 700 payload, PTP_MGMTMSG_PAYLOAD_OUTPUT_CLOCK_ENABLED_SIZE_OCTETS, 701 resp, &resp_len))) { 702 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 703 return rv; 704 } 705 706 /* Set host-maintained output clock enable Boolean. */ 707 if (enable) { 708 OUTPUT_CLOCK(clock_index).state |= (1 << TDPLL_OUTPUT_CLOCK_STATE_ENABLE_BIT); 709 } else { 710 OUTPUT_CLOCK(clock_index).state &= ~(1 << TDPLL_OUTPUT_CLOCK_STATE_ENABLE_BIT); 711 } 712 713 return BCM_E_NONE; 714 } 715 716 /* 717 * Function: 718 * bcm_tdpll_output_clock_synth_frequency_get() 719 * Purpose: 720 * Get output-clock (synthesizer) frequency. 721 * Parameters: 722 * unit - (IN) Unit number. 723 * stack_id - (IN) Stack identifier index. 724 * clock_index - (IN) Output clock index. 725 * synth_frequency - (OUT) Synthesizer frequency (Hz). 726 * tsevent_frequency - (OUT) TS event frequency (Hz). 727 * Returns: 728 * BCM_E_XXX - Function status. 729 * Notes: 730 */ 731 int 732 bcm_common_tdpll_output_clock_synth_frequency_get( 733 int unit, 734 int stack_id, 735 int clock_index, 736 uint32 *synth_frequency, 737 uint32 *tsevent_frequency) 738 { 739 int i; 740 int rv; 741 742 uint8 payload[PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS] = {0}; 743 uint8 resp[PTP_MGMTMSG_PAYLOAD_OUTPUT_CLOCK_SYNTH_FREQUENCY_SIZE_OCTETS] = {0}; 744 int resp_len = PTP_MGMTMSG_PAYLOAD_OUTPUT_CLOCK_SYNTH_FREQUENCY_SIZE_OCTETS; 745 746 bcm_ptp_port_identity_t portid; 747 748 if (BCM_FAILURE(rv = _bcm_common_tdpll_output_clock_index_validate(unit, clock_index))) { 749 PTP_ERROR_FUNC("_bcm_common_tdpll_output_clock_index_validate()"); 750 return rv; 751 } 752 753 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 754 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 755 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 756 return rv; 757 } 758 759 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 760 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 761 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 762 return rv; 763 } 764 765 /* Make indexed payload to get synthesizer frequency for specified output clock. */ 766 sal_memcpy(payload, "BCM\0\0\0", 6); 767 payload[6] = (uint8)clock_index; 768 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 769 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_OUTPUT_CLOCK_SYNTH_FREQUENCY, 770 payload, PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS, 771 resp, &resp_len))) { 772 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 773 return rv; 774 } 775 776 /* 777 * Parse response. 778 * Octet 0...5 : Custom management message key/identifier. 779 * BCM<null><null><null>. 780 * Octet 6 : Output clock index. 781 * Octet 7 : Reserved. 782 * Octet 8...11 : Synthesizer frequency (Hz). 783 * Octet 12...15 : TS event frequency (Hz). 784 */ 785 i = 6; /* Advance cursor past custom management message identifier. */ 786 ++i; /* Advance past output clock index. */ 787 ++i; /* Advance past reserved octet. */ 788 789 *synth_frequency = _bcm_ptp_uint32_read(resp + i); 790 i += 4; 791 *tsevent_frequency = _bcm_ptp_uint32_read(resp + i); 792 793 /* Set host-maintained output clock frequencies. */ 794 OUTPUT_CLOCK(clock_index).frequency.synth = *synth_frequency; 795 OUTPUT_CLOCK(clock_index).frequency.tsevent = *tsevent_frequency; 796 OUTPUT_CLOCK(clock_index).frequency.tsevent_quotient = *tsevent_frequency ? 797 (*synth_frequency + (*tsevent_frequency >> 1))/(*tsevent_frequency) : -1; 798 799 return BCM_E_NONE; 800 } 801 802 /* 803 * Function: 804 * bcm_tdpll_output_clock_synth_frequency_set() 805 * Purpose: 806 * Set output-clock (synthesizer) frequency. 807 * Parameters: 808 * unit - (IN) Unit number. 809 * stack_id - (IN) Stack identifier index. 810 * clock_index - (IN) Output clock index. 811 * synth_frequency - (IN) Synthesizer frequency (Hz). 812 * tsevent_frequency - (IN) TS event frequency (Hz). 813 * Returns: 814 * BCM_E_XXX - Function status. 815 * Notes: 816 */ 817 int 818 bcm_common_tdpll_output_clock_synth_frequency_set( 819 int unit, 820 int stack_id, 821 int clock_index, 822 uint32 synth_frequency, 823 uint32 tsevent_frequency) 824 { 825 int i; 826 int rv; 827 828 uint8 payload[PTP_MGMTMSG_PAYLOAD_OUTPUT_CLOCK_SYNTH_FREQUENCY_SIZE_OCTETS] = {0}; 829 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 830 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 831 832 bcm_ptp_port_identity_t portid; 833 834 if (BCM_FAILURE(rv = _bcm_common_tdpll_output_clock_index_validate(unit, clock_index))) { 835 PTP_ERROR_FUNC("_bcm_common_tdpll_output_clock_index_validate()"); 836 return rv; 837 } 838 839 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 840 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 841 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 842 return rv; 843 } 844 845 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 846 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 847 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 848 return rv; 849 } 850 851 /* 852 * CONSTRAINT: TS event frequency is a multiple of 1 kHz / 100 Hz. 853 * DPLL instances (and physical synthesizers bound to them) 854 * operate at 1 kHz / 100 Hz. 855 */ 856 if ((0 == tsevent_frequency) || (tsevent_frequency % BCM_TDPLL_FREQUENCY)) { 857 LOG_VERBOSE(BSL_LS_BCM_COMMON, 858 (BSL_META_U(unit, 859 "TS EVENT frequency is not a multiple of %u Hz. fTS: %u\n"), 860 (unsigned)BCM_TDPLL_FREQUENCY, (unsigned)tsevent_frequency)); 861 return BCM_E_PARAM; 862 } 863 864 /* 865 * CONSTRAINT: TS event frequency and synthesizer frequency are integrally 866 * related, N = f_synth / f_tsevent, such that TS events occur 867 * at every Nth synthesizer clock edge. 868 */ 869 if ((0 == synth_frequency) || (synth_frequency % tsevent_frequency)) { 870 LOG_VERBOSE(BSL_LS_BCM_COMMON, 871 (BSL_META_U(unit, 872 "SYNTH and TS EVENT frequencies are not integrally related. fSYNTH: %u fTS: %u"), 873 (unsigned)synth_frequency, (unsigned)tsevent_frequency)); 874 return BCM_E_PARAM; 875 } 876 877 /* 878 * Make payload. 879 * Octet 0...5 : Custom management message key/identifier. 880 * BCM<null><null><null>. 881 * Octet 6 : Output clock index. 882 * Octet 7 : Reserved. 883 * Octet 8...11 : Synthesizer frequency (Hz). 884 * Octet 12...15 : TS event frequency (Hz). 885 */ 886 sal_memcpy(payload, "BCM\0\0\0", 6); 887 i = 6; 888 payload[i++] = (uint8)clock_index; 889 payload[i++] = 0; 890 891 _bcm_ptp_uint32_write(payload+i, synth_frequency); 892 i += 4; 893 _bcm_ptp_uint32_write(payload+i, tsevent_frequency); 894 895 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 896 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_OUTPUT_CLOCK_SYNTH_FREQUENCY, 897 payload, PTP_MGMTMSG_PAYLOAD_OUTPUT_CLOCK_SYNTH_FREQUENCY_SIZE_OCTETS, 898 resp, &resp_len))) { 899 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 900 return rv; 901 } 902 903 /* Set host-maintained output clock frequencies. */ 904 OUTPUT_CLOCK(clock_index).frequency.synth = synth_frequency; 905 OUTPUT_CLOCK(clock_index).frequency.tsevent = tsevent_frequency; 906 OUTPUT_CLOCK(clock_index).frequency.tsevent_quotient = synth_frequency/tsevent_frequency; 907 908 return BCM_E_NONE; 909 } 910 911 /* 912 * Function: 913 * bcm_tdpll_output_clock_deriv_frequency_get() 914 * Purpose: 915 * Get synthesizer derivative-clock frequency. 916 * Parameters: 917 * unit - (IN) Unit number. 918 * stack_id - (IN) Stack identifier index. 919 * clock_index - (IN) Output clock index. 920 * deriv_frequency - (OUT) Derivative clock frequency (Hz). 921 * Returns: 922 * BCM_E_XXX - Function status. 923 * Notes: 924 */ 925 int 926 bcm_common_tdpll_output_clock_deriv_frequency_get( 927 int unit, 928 int stack_id, 929 int clock_index, 930 uint32 *deriv_frequency) 931 { 932 int i; 933 int rv; 934 935 uint32 synth_frequency; 936 937 uint8 payload[PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS] = {0}; 938 uint8 resp[PTP_MGMTMSG_PAYLOAD_OUTPUT_CLOCK_DERIV_FREQUENCY_SIZE_OCTETS] = {0}; 939 int resp_len = PTP_MGMTMSG_PAYLOAD_OUTPUT_CLOCK_DERIV_FREQUENCY_SIZE_OCTETS; 940 941 bcm_ptp_port_identity_t portid; 942 943 if (BCM_FAILURE(rv = _bcm_common_tdpll_output_clock_index_validate(unit, clock_index))) { 944 PTP_ERROR_FUNC("_bcm_common_tdpll_output_clock_index_validate()"); 945 return rv; 946 } 947 948 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 949 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 950 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 951 return rv; 952 } 953 954 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 955 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 956 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 957 return rv; 958 } 959 960 /* Make indexed payload to get derivative-clock frequency(ies) for specified output clock. */ 961 sal_memcpy(payload, "BCM\0\0\0", 6); 962 payload[6] = (uint8)clock_index; 963 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 964 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_OUTPUT_CLOCK_DERIV_FREQUENCY, 965 payload, PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS, 966 resp, &resp_len))) { 967 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 968 return rv; 969 } 970 971 /* 972 * Parse response. 973 * Octet 0...5 : Custom management message key/identifier. 974 * BCM<null><null><null>. 975 * Octet 6 : Output clock index. 976 * Octet 7 : Reserved. 977 * Octet 8...11 : Derivative clock frequency (Hz). 978 */ 979 i = 6; /* Advance cursor past custom management message identifier. */ 980 ++i; /* Advance past output clock index. */ 981 ++i; /* Advance past reserved octet. */ 982 983 *deriv_frequency = _bcm_ptp_uint32_read(resp + i); 984 985 /* Set host-maintained output clock frequencies and ratios. */ 986 OUTPUT_CLOCK(clock_index).frequency.deriv = *deriv_frequency; 987 988 synth_frequency = OUTPUT_CLOCK(clock_index).frequency.synth; 989 OUTPUT_CLOCK(clock_index).frequency.deriv_quotient = *deriv_frequency ? 990 (synth_frequency + (*deriv_frequency >> 1))/(*deriv_frequency) : -1; 991 992 return BCM_E_NONE; 993 } 994 995 /* 996 * Function: 997 * bcm_tdpll_output_clock_deriv_frequency_set() 998 * Purpose: 999 * Set synthesizer derivative clock frequency. 1000 * Parameters: 1001 * unit - (IN) Unit number. 1002 * stack_id - (IN) Stack identifier index. 1003 * clock_index - (IN) Output clock index. 1004 * deriv_frequency - (IN) Derivative clock frequency (Hz). 1005 * Returns: 1006 * BCM_E_XXX - Function status. 1007 * Notes: 1008 */ 1009 int 1010 bcm_common_tdpll_output_clock_deriv_frequency_set( 1011 int unit, 1012 int stack_id, 1013 int clock_index, 1014 uint32 deriv_frequency) 1015 { 1016 int i; 1017 int rv; 1018 1019 uint32 synth_frequency; 1020 1021 uint8 payload[PTP_MGMTMSG_PAYLOAD_OUTPUT_CLOCK_DERIV_FREQUENCY_SIZE_OCTETS] = {0}; 1022 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1023 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1024 1025 bcm_ptp_port_identity_t portid; 1026 1027 if (BCM_FAILURE(rv = _bcm_common_tdpll_output_clock_index_validate(unit, clock_index))) { 1028 PTP_ERROR_FUNC("_bcm_common_tdpll_output_clock_index_validate()"); 1029 return rv; 1030 } 1031 1032 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 1033 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1034 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1035 return rv; 1036 } 1037 1038 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 1039 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 1040 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 1041 return rv; 1042 } 1043 1044 /* 1045 * CONSTRAINT: Derivative clock frequency and synthesizer frequency are 1046 * integrally related, i.e. M = f_synth / f_deriv, such that 1047 * derivative clock pulses occur every Mth synthesizer clock 1048 * pulse. 1049 */ 1050 synth_frequency = OUTPUT_CLOCK(clock_index).frequency.synth; 1051 if (deriv_frequency) { 1052 if ((0 == synth_frequency) || (synth_frequency % deriv_frequency)) { 1053 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1054 (BSL_META_U(unit, 1055 "SYNTH and DERIV frequencies are not integrally related. fSYNTH: %u fDERIV: %u"), 1056 (unsigned)synth_frequency, (unsigned)deriv_frequency)); 1057 return BCM_E_PARAM; 1058 } 1059 } 1060 1061 /* 1062 * Make payload. 1063 * Octet 0...5 : Custom management message key/identifier. 1064 * BCM<null><null><null>. 1065 * Octet 6 : Output clock index. 1066 * Octet 7 : Reserved. 1067 * Octet 8...11 : Derivative-clock frequency (Hz). 1068 */ 1069 sal_memcpy(payload, "BCM\0\0\0", 6); 1070 i = 6; 1071 payload[i++] = (uint8)clock_index; 1072 payload[i++] = 0; 1073 1074 _bcm_ptp_uint32_write(payload+i, deriv_frequency); 1075 1076 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 1077 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_OUTPUT_CLOCK_DERIV_FREQUENCY, 1078 payload, PTP_MGMTMSG_PAYLOAD_OUTPUT_CLOCK_DERIV_FREQUENCY_SIZE_OCTETS, 1079 resp, &resp_len))) { 1080 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 1081 return rv; 1082 } 1083 1084 /* Set host-maintained output clock frequencies. */ 1085 OUTPUT_CLOCK(clock_index).frequency.deriv = deriv_frequency; 1086 1087 OUTPUT_CLOCK(clock_index).frequency.deriv_quotient = deriv_frequency ? 1088 synth_frequency/deriv_frequency : -1; 1089 1090 return BCM_E_NONE; 1091 } 1092 1093 /* 1094 * Function: 1095 * bcm_tdpll_output_clock_holdover_data_get() 1096 * Purpose: 1097 * Get holdover configuration data. 1098 * Parameters: 1099 * unit - (IN) Unit number. 1100 * stack_id - (IN) Stack identifier index. 1101 * clock_index - (IN) Output clock index. 1102 * hdata - (OUT) Holdover configuration data. 1103 * Returns: 1104 * BCM_E_XXX - Function status. 1105 * Notes: 1106 */ 1107 int 1108 bcm_common_tdpll_output_clock_holdover_data_get( 1109 int unit, 1110 int stack_id, 1111 int clock_index, 1112 bcm_tdpll_holdover_data_t *hdata) 1113 { 1114 int rv; 1115 int i; 1116 1117 uint8 payload[PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS] = {0}; 1118 uint8 resp[PTP_MGMTMSG_PAYLOAD_HOLDOVER_DATA_SIZE_OCTETS] = {0}; 1119 int resp_len = PTP_MGMTMSG_PAYLOAD_HOLDOVER_DATA_SIZE_OCTETS; 1120 1121 bcm_ptp_port_identity_t portid; 1122 1123 if (BCM_FAILURE(rv = _bcm_common_tdpll_output_clock_index_validate(unit, clock_index))) { 1124 PTP_ERROR_FUNC("_bcm_common_tdpll_output_clock_index_validate()"); 1125 return rv; 1126 } 1127 1128 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 1129 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1130 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1131 return rv; 1132 } 1133 1134 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 1135 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 1136 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 1137 return rv; 1138 } 1139 1140 /* Make indexed payload to get holdover data for specified output clock. */ 1141 sal_memcpy(payload, "BCM\0\0\0", 6); 1142 payload[6] = (uint8)clock_index; 1143 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 1144 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_HOLDOVER_DATA, 1145 payload, PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS, 1146 resp, &resp_len))) { 1147 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 1148 return rv; 1149 } 1150 1151 /* 1152 * Parse response. 1153 * Octet 0...5 : Custom management message key/identifier. 1154 * BCM<null><null><null>. 1155 * Octet 6 : Output clock index. 1156 * Octet 7 : Reserved. 1157 * Octet 8...11 : Instantaneous holdover frequency (ppt). 1158 * Octet 12...15 : 1s average holdover frequency (ppt). 1159 * Octet 16...19 : Manual holdover frequency (ppt). 1160 * Octet 20...23 : Fast-average holdover frequency (ppt). 1161 * Octet 24...27 : Slow-average holdover frequency (ppt). 1162 * Octet 28 : Fast-average valid Boolean. 1163 * Octet 29 : Slow-average valid Boolean. 1164 * Octet 30 : Holdover mode. 1165 * Octet 31 : Reserved. 1166 */ 1167 i = 6; /* Advance cursor past custom management message identifier. */ 1168 ++i; /* Advance past output clock index. */ 1169 ++i; /* Advance past reserved octet. */ 1170 1171 hdata->freq_instantaneous = (bcm_tdpll_frequency_correction_t)_bcm_ptp_uint32_read(resp + i); 1172 i += 4; 1173 hdata->freq_avg1s = (bcm_tdpll_frequency_correction_t)_bcm_ptp_uint32_read(resp + i); 1174 i += 4; 1175 hdata->freq_manual = (bcm_tdpll_frequency_correction_t)_bcm_ptp_uint32_read(resp + i); 1176 i += 4; 1177 hdata->freq_fast_average = (bcm_tdpll_frequency_correction_t)_bcm_ptp_uint32_read(resp + i); 1178 i += 4; 1179 hdata->freq_slow_average = (bcm_tdpll_frequency_correction_t)_bcm_ptp_uint32_read(resp + i); 1180 i += 4; 1181 hdata->freq_fast_average_valid = resp[i++] ? 1:0; 1182 hdata->freq_slow_average_valid = resp[i++] ? 1:0; 1183 hdata->mode = resp[i++]; 1184 1185 return BCM_E_NONE; 1186 } 1187 1188 /* 1189 * Function: 1190 * bcm_tdpll_output_clock_holdover_frequency_set() 1191 * Purpose: 1192 * Set manual holdover frequency correction. 1193 * Parameters: 1194 * unit - (IN) Unit number. 1195 * stack_id - (IN) Stack identifier index. 1196 * clock_index - (IN) Output clock index. 1197 * hfreq - (IN) Holdover frequency correction (ppt). 1198 * Returns: 1199 * BCM_E_XXX - Function status. 1200 * Notes: 1201 * Manual frequency correction is used if holdover mode is manual. 1202 */ 1203 int 1204 bcm_common_tdpll_output_clock_holdover_frequency_set( 1205 int unit, 1206 int stack_id, 1207 int clock_index, 1208 bcm_tdpll_frequency_correction_t hfreq) 1209 { 1210 int rv; 1211 int i; 1212 1213 uint8 payload[PTP_MGMTMSG_PAYLOAD_HOLDOVER_FREQUENCY_SIZE_OCTETS] = {0}; 1214 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1215 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1216 1217 bcm_ptp_port_identity_t portid; 1218 1219 if (BCM_FAILURE(rv = _bcm_common_tdpll_output_clock_index_validate(unit, clock_index))) { 1220 PTP_ERROR_FUNC("_bcm_common_tdpll_output_clock_index_validate()"); 1221 return rv; 1222 } 1223 1224 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 1225 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1226 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1227 return rv; 1228 } 1229 1230 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 1231 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 1232 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 1233 return rv; 1234 } 1235 1236 /* 1237 * Make payload. 1238 * Octet 0...5 : Custom management message key/identifier. 1239 * BCM<null><null><null>. 1240 * Octet 6 : Output clock index. 1241 * Octet 7 : Reserved. 1242 * Octet 8...11 : Holdover frequency (ppt). 1243 */ 1244 sal_memcpy(payload, "BCM\0\0\0", 6); 1245 i = 6; 1246 payload[i++] = (uint8)clock_index; 1247 payload[i++] = 0; 1248 _bcm_ptp_uint32_write(payload + i, (uint32)hfreq); 1249 1250 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 1251 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_HOLDOVER_FREQUENCY, 1252 payload, PTP_MGMTMSG_PAYLOAD_HOLDOVER_FREQUENCY_SIZE_OCTETS, 1253 resp, &resp_len))) { 1254 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 1255 return rv; 1256 } 1257 1258 return BCM_E_NONE; 1259 } 1260 1261 /* 1262 * Function: 1263 * bcm_tdpll_output_clock_holdover_mode_get() 1264 * Purpose: 1265 * Get holdover mode. 1266 * |Manual|Instantaneous|One-Second|Fast Average|Slow Average| 1267 * Parameters: 1268 * unit - (IN) Unit number. 1269 * stack_id - (IN) Stack identifier index. 1270 * clock_index - (IN) Output clock index. 1271 * hmode - (OUT) Holdover mode. 1272 * Returns: 1273 * BCM_E_XXX - Function status. 1274 * Notes: 1275 */ 1276 int 1277 bcm_common_tdpll_output_clock_holdover_mode_get( 1278 int unit, 1279 int stack_id, 1280 int clock_index, 1281 bcm_tdpll_holdover_mode_t *hmode) 1282 { 1283 int rv; 1284 1285 uint8 payload[PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS] = {0}; 1286 uint8 resp[PTP_MGMTMSG_PAYLOAD_HOLDOVER_MODE_SIZE_OCTETS] = {0}; 1287 int resp_len = PTP_MGMTMSG_PAYLOAD_HOLDOVER_MODE_SIZE_OCTETS; 1288 1289 bcm_ptp_port_identity_t portid; 1290 1291 if (BCM_FAILURE(rv = _bcm_common_tdpll_output_clock_index_validate(unit, clock_index))) { 1292 PTP_ERROR_FUNC("_bcm_common_tdpll_output_clock_index_validate()"); 1293 return rv; 1294 } 1295 1296 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 1297 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1298 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1299 return rv; 1300 } 1301 1302 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 1303 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 1304 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 1305 return rv; 1306 } 1307 1308 /* Make indexed payload to get holdover mode for specified output clock. */ 1309 sal_memcpy(payload, "BCM\0\0\0", 6); 1310 payload[6] = (uint8)clock_index; 1311 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 1312 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_HOLDOVER_MODE, 1313 payload, PTP_MGMTMSG_PAYLOAD_INDEXED_PROPRIETARY_MSG_SIZE_OCTETS, 1314 resp, &resp_len))) { 1315 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 1316 return rv; 1317 } 1318 1319 /* 1320 * Parse response. 1321 * Octet 0...5 : Custom management message key/identifier. 1322 * BCM<null><null><null>. 1323 * Octet 6 : Output clock index. 1324 * Octet 7 : Holdover mode. 1325 */ 1326 *hmode = resp[7]; 1327 1328 return BCM_E_NONE; 1329 } 1330 1331 /* 1332 * Function: 1333 * bcm_tdpll_output_clock_holdover_mode_set() 1334 * Purpose: 1335 * Set holdover mode. 1336 * |Manual|Instantaneous|Fast Average|Slow Average| 1337 * Parameters: 1338 * unit - (IN) Unit number. 1339 * stack_id - (IN) Stack identifier index. 1340 * clock_index - (IN) Output clock index. 1341 * hmode - (IN) Holdover mode. 1342 * Returns: 1343 * BCM_E_XXX - Function status. 1344 * Notes: 1345 */ 1346 int 1347 bcm_common_tdpll_output_clock_holdover_mode_set( 1348 int unit, 1349 int stack_id, 1350 int clock_index, 1351 bcm_tdpll_holdover_mode_t hmode) 1352 { 1353 int rv; 1354 int i; 1355 1356 uint8 payload[PTP_MGMTMSG_PAYLOAD_HOLDOVER_MODE_SIZE_OCTETS] = {0}; 1357 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1358 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1359 1360 bcm_ptp_port_identity_t portid; 1361 1362 if (BCM_FAILURE(rv = _bcm_common_tdpll_output_clock_index_validate(unit, clock_index))) { 1363 PTP_ERROR_FUNC("_bcm_common_tdpll_output_clock_index_validate()"); 1364 return rv; 1365 } 1366 1367 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 1368 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1369 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1370 return rv; 1371 } 1372 1373 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 1374 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 1375 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 1376 return rv; 1377 } 1378 1379 /* 1380 * Make payload. 1381 * Octet 0...5 : Custom management message key/identifier. 1382 * BCM<null><null><null>. 1383 * Octet 6 : Output clock index. 1384 * Octet 7 : Holdover mode. 1385 */ 1386 sal_memcpy(payload, "BCM\0\0\0", 6); 1387 i = 6; 1388 payload[i++] = (uint8)clock_index; 1389 payload[i++] = (uint8)hmode; 1390 1391 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 1392 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_HOLDOVER_MODE, 1393 payload, PTP_MGMTMSG_PAYLOAD_HOLDOVER_MODE_SIZE_OCTETS, 1394 resp, &resp_len))) { 1395 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 1396 return rv; 1397 } 1398 1399 return BCM_E_NONE; 1400 } 1401 1402 /* 1403 * Function: 1404 * bcm_tdpll_output_clock_holdover_reset() 1405 * Purpose: 1406 * Reset holdover frequency calculations. 1407 * Parameters: 1408 * unit - (IN) Unit number. 1409 * stack_id - (IN) Stack identifier index. 1410 * clock_index - (IN) Output clock index. 1411 * Returns: 1412 * BCM_E_XXX - Function status. 1413 * Notes: 1414 */ 1415 int 1416 bcm_common_tdpll_output_clock_holdover_reset( 1417 int unit, 1418 int stack_id, 1419 int clock_index) 1420 { 1421 int rv; 1422 1423 uint8 payload[PTP_MGMTMSG_PAYLOAD_HOLDOVER_RESET_SIZE_OCTETS] = {0}; 1424 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 1425 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 1426 1427 bcm_ptp_port_identity_t portid; 1428 1429 if (BCM_FAILURE(rv = _bcm_common_tdpll_output_clock_index_validate(unit, clock_index))) { 1430 PTP_ERROR_FUNC("_bcm_common_tdpll_output_clock_index_validate()"); 1431 return rv; 1432 } 1433 1434 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 1435 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1436 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1437 return rv; 1438 } 1439 1440 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 1441 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 1442 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 1443 return rv; 1444 } 1445 1446 /* 1447 * Make payload. 1448 * Octet 0...5 : Custom management message key/identifier. 1449 * BCM<null><null><null>. 1450 * Octet 6 : Output clock index. 1451 * Octet 7 : Reserved. 1452 */ 1453 sal_memcpy(payload, "BCM\0\0\0", 6); 1454 payload[6] = (uint8)clock_index; 1455 1456 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 1457 &portid, PTP_MGMTMSG_CMD, PTP_MGMTMSG_ID_HOLDOVER_RESET, 1458 payload, PTP_MGMTMSG_PAYLOAD_HOLDOVER_RESET_SIZE_OCTETS, 1459 resp, &resp_len))) { 1460 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 1461 return rv; 1462 } 1463 1464 return BCM_E_NONE; 1465 } 1466 1467 #endif /* defined(INCLUDE_PTP) */