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_dpll.c (32632B)


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