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

timesource.c (52080B)


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