openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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) */