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

modular.c (22229B)


      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:    modular.c
      8  *
      9  * Purpose: 
     10  *
     11  * Functions:
     12  *      bcm_common_ptp_modular_enable_get
     13  *      bcm_common_ptp_modular_enable_set
     14  *      bcm_common_ptp_modular_phyts_get
     15  *      bcm_common_ptp_modular_phyts_set
     16  *      bcm_common_ptp_modular_portbitmap_get
     17  *      bcm_common_ptp_modular_portbitmap_set
     18  *      bcm_common_ptp_modular_verbose_get
     19  *      bcm_common_ptp_modular_verbose_set
     20  *
     21  *      _bcm_ptp_modular_init 
     22  *      _bcm_ptp_modular_shutdown
     23  *      _bcm_ptp_modular_supervisor
     24  *      _bcm_ptp_modular_physync_synchronize
     25  *      _bcm_ptp_modular_physync_configure
     26  */
     27 
     28 #if defined(INCLUDE_PTP)
     29 
     30 #include <shared/util.h>
     31 #include <bcm/ptp.h>
     32 #include <bcm_int/common/ptp.h>
     33 #include <bcm_int/ptp_common.h>
     34 
     35 #include <bcm/port.h>
     36 
     37 #include <bcm/error.h>
     38 
     39 #include <soc/dport.h>
     40 
     41 /* Definitions. */
     42 #define PTP_MODULAR_SUPERVISOR_DPC_TIME_USEC_DEFAULT              (1000000)
     43 #define PTP_MODULAR_SUPERVISOR_DPC_TIME_USEC_IDLE                 (3000000)
     44 #define PTP_MODULAR_PHYSYNC_FRAMESYNC_WAIT_USEC                      (1000)
     45 
     46 #define PTP_MODULAR_PHYSYNC_REFPHASE_OFFSET_SEC                         (1)
     47 
     48 #define PTP_MODULAR_PHYSYNC_FREQUENCY_PIN                              (-1)
     49 #define PTP_MODULAR_PHYSYNC_FRAMESYNC_PIN                               (3)
     50 
     51 /* Macros. */
     52 
     53 /* Types. */
     54 typedef struct _bcm_ptp_modular_options_s {
     55     int enable;
     56     int verbose;
     57     int phyts;
     58     int framesync_pin;
     59     bcm_pbmp_t pbmp;
     60 } _bcm_ptp_modular_options_t;
     61 
     62 /* Constants and variables. */
     63 static _bcm_ptp_modular_options_t modular_options = {
     64     0,
     65     0,
     66     0,
     67     0,
     68     {{0x00000000}}
     69 };
     70 
     71 static uint32 modular_flags;
     72 static shr_rdpc_t modular_supervisor_rdpc;
     73 
     74 /* Static functions. */
     75 static sal_usecs_t _bcm_ptp_modular_supervisor(
     76     void **arg_unit, void **arg_ptp_id,
     77     void **arg_clock_num, void **unused);
     78 
     79 static int _bcm_ptp_modular_physync_synchronize(
     80     int unit, bcm_ptp_stack_id_t ptp_id, int clock_num);
     81 
     82 static int _bcm_ptp_modular_physync_configure(
     83     int unit, bcm_port_t port, uint64 ref_phase);
     84 
     85 /*
     86  * Function:
     87  *      _bcm_ptp_modular_init
     88  * Purpose:
     89  *      Initialize the modular system.
     90  * Parameters:
     91  *      unit      - (IN) Unit number.
     92  *      ptp_id    - (IN) PTP stack ID.
     93  *      clock_num - (IN) PTP clock number.
     94  *      flags     - (IN) Modular system control flags. (UNUSED)
     95  * Returns:
     96  *      BCM_E_XXX - Function status.
     97  * Notes:
     98  */
     99 int
    100 _bcm_ptp_modular_init(
    101     int unit,
    102     bcm_ptp_stack_id_t ptp_id,
    103     int clock_num,
    104     uint32 flags)
    105 {
    106     int rv;
    107 
    108     if (shr_rdpc_callback_created(&modular_supervisor_rdpc) == BCM_E_INIT) {
    109         /* RDPC (and associated lock) is left in place on cleanup, so only create it once */
    110         rv = shr_rdpc_callback_create(&modular_supervisor_rdpc, &_bcm_ptp_modular_supervisor);
    111     } else {
    112         rv = shr_rdpc_callback_stop(&modular_supervisor_rdpc);
    113     }
    114     return rv;
    115 }
    116 
    117 /*
    118  * Function:
    119  *      _bcm_ptp_modular_shutdown
    120  * Purpose:
    121  *      Shut down the modular system.
    122  * Parameters:
    123  *      unit      - (IN) Unit number.
    124  *      ptp_id    - (IN) PTP stack ID.
    125  *      clock_num - (IN) PTP clock number.
    126  * Returns:
    127  *      BCM_E_XXX - Function status.
    128  * Notes:
    129  */
    130 int
    131 _bcm_ptp_modular_shutdown(
    132     int unit,
    133     bcm_ptp_stack_id_t ptp_id,
    134     int clock_num)
    135 {
    136     int rv;
    137     /* Cancel modular system supervisor repeating delayed procedure call. */
    138     rv = shr_rdpc_callback_stop(&modular_supervisor_rdpc);
    139     return rv;
    140 }
    141 
    142 /*
    143  * Function:
    144  *      bcm_common_ptp_modular_enable_get
    145  * Purpose:
    146  *      Get enable/disable state of modular system functionality.
    147  * Parameters:
    148  *      unit      - (IN)  Unit number.
    149  *      ptp_id    - (IN)  PTP stack ID.
    150  *      clock_num - (IN)  PTP clock number.
    151  *      enable    - (OUT) Enable Boolean.
    152  *      flags     - (OUT) Modular system control flags. (UNUSED)
    153  * Returns:
    154  *      BCM_E_XXX - Function status.
    155  * Notes:
    156  */
    157 int
    158 bcm_common_ptp_modular_enable_get(
    159     int unit,
    160     bcm_ptp_stack_id_t ptp_id,
    161     int clock_num,
    162     int *enable,
    163     uint32 *flags)
    164 {
    165     int rv;
    166 
    167     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    168             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    169         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    170         return rv;
    171     }
    172 
    173     *enable = modular_options.enable;
    174     *flags = modular_flags;
    175 
    176     return BCM_E_NONE;
    177 }
    178 
    179 /*
    180  * Function:
    181  *      bcm_common_ptp_modular_enable_set
    182  * Purpose:
    183  *      Set enable/disable state of modular system functionality.
    184  * Parameters:
    185  *      unit      - (IN) Unit number.
    186  *      ptp_id    - (IN) PTP stack ID.
    187  *      clock_num - (IN) PTP clock number.
    188  *      enable    - (IN) Enable Boolean.
    189  *      flags     - (IN) Modular system control flags. (UNUSED)
    190  * Returns:
    191  *      BCM_E_XXX - Function status.
    192  * Notes:
    193  */
    194 int
    195 bcm_common_ptp_modular_enable_set(
    196     int unit,
    197     bcm_ptp_stack_id_t ptp_id,
    198     int clock_num,
    199     int enable,
    200     uint32 flags)
    201 {
    202     int rv;
    203     int i;
    204 
    205     uint8 payload[PTP_MGMTMSG_PAYLOAD_TELECOM_PROFILE_ENABLED_SIZE_OCTETS] = {0};
    206     uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS];
    207     int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS;
    208 
    209     bcm_ptp_port_identity_t portid;
    210 
    211     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    212             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    213         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    214         return rv;
    215     }
    216 
    217     /*
    218      * Make payload.
    219      *    Octet 0...5 : Custom management message key/identifier.
    220      *                  BCM<null><null><null>.
    221      *    Octet 6     : Modular system enabled Boolean.
    222      *    Octet 7     : Reserved.
    223      */
    224     sal_memcpy(payload, "BCM\0\0\0", 6);
    225     i = 6;
    226     payload[i] = enable ? 1:0;
    227 
    228     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id,
    229             clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) {
    230         PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()");
    231         return rv;
    232     }
    233 
    234     if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num,
    235             &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_MODULAR_SYSTEM_ENABLED,
    236             payload, PTP_MGMTMSG_PAYLOAD_MODULAR_SYSTEM_ENABLED_SIZE_OCTETS,
    237             resp, &resp_len))) {
    238         PTP_ERROR_FUNC("_bcm_ptp_management_message_send()");
    239         return rv;
    240     }
    241 
    242     /* Start modular system supervisor DPC iff modular system is enabled. */
    243     if (enable) {
    244         rv = shr_rdpc_callback_start(&modular_supervisor_rdpc, PTP_MODULAR_SUPERVISOR_DPC_TIME_USEC_DEFAULT,
    245                                      INT_TO_PTR(unit), INT_TO_PTR(ptp_id), INT_TO_PTR(clock_num), 0);
    246     } else {
    247         rv = shr_rdpc_callback_stop(&modular_supervisor_rdpc);
    248     }
    249 
    250     modular_options.enable = enable;
    251     modular_flags = flags;
    252 
    253     return BCM_E_NONE;
    254 }
    255 
    256 /*
    257  * Function:
    258  *      bcm_common_ptp_modular_verbose_get
    259  * Purpose:
    260  *      Get verbose program control option of modular system functionality.
    261  * Parameters:
    262  *      unit      - (IN)  Unit number.
    263  *      ptp_id    - (IN)  PTP stack ID.
    264  *      clock_num - (IN)  PTP clock number.
    265  *      verbose   - (OUT) Verbose Boolean.
    266  * Returns:
    267  *      BCM_E_XXX - Function status.
    268  * Notes:
    269  */
    270 int
    271 bcm_common_ptp_modular_verbose_get(
    272     int unit,
    273     bcm_ptp_stack_id_t ptp_id,
    274     int clock_num,
    275     int *verbose)
    276 {
    277     int rv;
    278 
    279     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    280             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    281         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    282         return rv;
    283     }
    284 
    285     *verbose = modular_options.verbose;
    286     return BCM_E_NONE;
    287 }
    288 
    289 /*
    290  * Function:
    291  *      bcm_common_ptp_modular_verbose_set
    292  * Purpose:
    293  *      Set verbose program control option of modular system functionality.
    294  * Parameters:
    295  *      unit      - (IN) Unit number.
    296  *      ptp_id    - (IN) PTP stack ID.
    297  *      clock_num - (IN) PTP clock number.
    298  *      verbose   - (IN) Verbose Boolean.
    299  * Returns:
    300  *      BCM_E_XXX - Function status.
    301  * Notes:
    302  */
    303 int
    304 bcm_common_ptp_modular_verbose_set(
    305     int unit,
    306     bcm_ptp_stack_id_t ptp_id,
    307     int clock_num,
    308     int verbose)
    309 {
    310     int rv;
    311 
    312     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    313             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    314         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    315         return rv;
    316     }
    317 
    318     modular_options.verbose = verbose;
    319     return BCM_E_NONE;
    320 }
    321 
    322 /*
    323  * Function:
    324  *      bcm_common_ptp_modular_portbitmap_get
    325  * Purpose:
    326  *      Get PHY port bitmap.
    327  * Parameters:
    328  *      unit      - (IN)  Unit number.
    329  *      ptp_id    - (IN)  PTP stack ID.
    330  *      clock_num - (IN)  PTP clock number.
    331  *      pbmp      - (OUT) Port bitmap.
    332  * Returns:
    333  *      BCM_E_XXX - Function status.
    334  * Notes:
    335  */
    336 int
    337 bcm_common_ptp_modular_portbitmap_get(
    338     int unit,
    339     bcm_ptp_stack_id_t ptp_id,
    340     int clock_num,
    341     bcm_pbmp_t *pbmp)
    342 {
    343     int rv;
    344 
    345     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    346             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    347         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    348         return rv;
    349     }
    350 
    351     *pbmp = modular_options.pbmp;
    352     return BCM_E_NONE;
    353 }
    354 
    355 /*
    356  * Function:
    357  *      bcm_common_ptp_modular_portbitmap_set
    358  * Purpose:
    359  *      Set PHY port bitmap.
    360  * Parameters:
    361  *      unit      - (IN) Unit number.
    362  *      ptp_id    - (IN) PTP stack ID.
    363  *      clock_num - (IN) PTP clock number.
    364  *      pbmp      - (IN) Port bitmap.
    365  * Returns:
    366  *      BCM_E_XXX - Function status.
    367  * Notes:
    368  */
    369 int
    370 bcm_common_ptp_modular_portbitmap_set(
    371     int unit,
    372     bcm_ptp_stack_id_t ptp_id,
    373     int clock_num,
    374     bcm_pbmp_t pbmp)
    375 {
    376     int rv;
    377 
    378     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    379             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    380         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    381         return rv;
    382     }
    383 
    384     modular_options.pbmp = pbmp;
    385     return BCM_E_NONE;
    386 }
    387 
    388 /*
    389  * Function:
    390  *      bcm_common_ptp_modular_phyts_get
    391  * Purpose:
    392  *      Get PHY timestamping configuration state and data.
    393  * Parameters:
    394  *      unit          - (IN)  Unit number.
    395  *      ptp_id        - (IN)  PTP stack ID.
    396  *      clock_num     - (IN)  PTP clock number.
    397  *      phyts         - (OUT) PHY timestamping Boolean.
    398  *      framesync_pin - (OUT) Framesync GPIO pin.
    399  * Returns:
    400  *      BCM_E_XXX - Function status.
    401  * Notes:
    402  */
    403 int
    404 bcm_common_ptp_modular_phyts_get(
    405     int unit,
    406     bcm_ptp_stack_id_t ptp_id,
    407     int clock_num,
    408     int *phyts,
    409     int *framesync_pin)
    410 {
    411     int rv;
    412 
    413     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    414             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    415         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    416         return rv;
    417     }
    418 
    419     *phyts = modular_options.phyts;
    420     *framesync_pin = modular_options.framesync_pin;
    421     return BCM_E_NONE;
    422 }
    423 
    424 /*
    425  * Function:
    426  *      bcm_common_ptp_modular_phyts_set
    427  * Purpose:
    428  *      Set PHY timestamping configuration state and data.
    429  * Parameters:
    430  *      unit          - (IN) Unit number.
    431  *      ptp_id        - (IN) PTP stack ID.
    432  *      clock_num     - (IN) PTP clock number.
    433  *      phyts         - (IN) PHY timestamping Boolean.
    434  *      framesync_pin - (IN) Framesync GPIO pin.
    435  * Returns:
    436  *      BCM_E_XXX - Function status.
    437  * Notes:
    438  */
    439 int
    440 bcm_common_ptp_modular_phyts_set(
    441     int unit,
    442     bcm_ptp_stack_id_t ptp_id,
    443     int clock_num,
    444     int phyts,
    445     int framesync_pin)
    446 {
    447     int rv;
    448 
    449     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    450             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    451         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    452         return rv;
    453     }
    454 
    455     modular_options.phyts = phyts;
    456     modular_options.framesync_pin = framesync_pin;
    457     return BCM_E_NONE;
    458 }
    459 
    460 /*
    461  * Function:
    462  *      _bcm_ptp_modular_supervisor
    463  * Purpose:
    464  *      Run modular system supervisor (as RDPC).
    465  * Parameters:
    466  *      arg_unit      - (IN) Unit number (as void**).
    467  *      arg_ptp_id    - (IN) PTP stack ID (as void**).
    468  *      arg_clock_num - (IN) PTP clock number (as void**).
    469  *      unused        - (IN) Unused.
    470  * Returns:
    471  *      Interval before next call
    472  * Notes:
    473  */
    474 static sal_usecs_t
    475 _bcm_ptp_modular_supervisor(
    476     void **arg_unit,
    477     void **arg_ptp_id,
    478     void **arg_clock_num,
    479     void **unused)
    480 {
    481     int rv;
    482 
    483     int unit = PTR_TO_INT(*arg_unit);
    484     bcm_ptp_stack_id_t ptp_id = (bcm_ptp_stack_id_t)PTR_TO_INT(*arg_ptp_id);
    485     int clock_num = PTR_TO_INT(*arg_clock_num);
    486 
    487     if (0 == modular_options.phyts) {
    488         /* IDLE. PHY timestamping option is not currently set. */
    489         return PTP_MODULAR_SUPERVISOR_DPC_TIME_USEC_IDLE;
    490     } else if (BCM_FAILURE(rv = _bcm_ptp_modular_physync_synchronize(unit, ptp_id, clock_num))) {
    491         PTP_ERROR_FUNC("_bcm_ptp_modular_physync_synchronize()");
    492         return PTP_MODULAR_SUPERVISOR_DPC_TIME_USEC_IDLE;
    493     } else {
    494         return PTP_MODULAR_SUPERVISOR_DPC_TIME_USEC_DEFAULT;
    495     }
    496 }
    497 
    498 /*
    499  * Function:
    500  *      _bcm_ptp_modular_physync_synchronize
    501  * Purpose:
    502  *      Synchronize PHYs.
    503  * Parameters:
    504  *      unit      - (IN) Unit number.
    505  *      ptp_id    - (IN) PTP stack ID.
    506  *      clock_num - (IN) PTP clock number.
    507  * Returns:
    508  *      BCM_E_XXX - Function status.
    509  * Notes:
    510  */
    511 static int
    512 _bcm_ptp_modular_physync_synchronize(
    513     int unit,
    514     bcm_ptp_stack_id_t ptp_id,
    515     int clock_num)
    516 {
    517     int rv;
    518     int i;
    519 
    520     uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS];
    521     int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS;
    522 
    523     bcm_ptp_port_identity_t portid;
    524 
    525     uint8 physync_reqd = 0;
    526     uint64 localTime_sec;
    527     uint32 localTime_nsec;
    528     uint64 physyncTime_nsec;
    529 
    530     soc_port_t p, dport;
    531     bcm_ptp_sync_phy_input_t physync_input;
    532 
    533     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    534             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    535         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    536         return rv;
    537     }
    538 
    539     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id,
    540             clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) {
    541         PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()");
    542         return rv;
    543     }
    544 
    545     /* Query stack to determine whether PHY synchronization is required. */
    546     if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id,
    547             clock_num, &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_PHYSYNC_STATE,
    548             0, 0, resp, &resp_len))) {
    549         PTP_ERROR_FUNC("_bcm_ptp_management_message_send()");
    550         return rv;
    551     }
    552 
    553     /*
    554      * Parse response.
    555      *    Octet 0...5  : Custom management message key/identifier.
    556      *                   BCM<null><null><null>.
    557      *    Octet 6      : PHY synchronization required Boolean.
    558      *    Octet 7      : Reserved.
    559      *    Octet 8...15 : Stack local time (sec).
    560      *    Octet 16...19: stack local time (nsec).
    561      */
    562     i = 6; /* Advance cursor past custom management message identifier. */
    563     physync_reqd = resp[i++];
    564     i++;   /* Advance cursor past reserved octet. */
    565 
    566     localTime_sec = _bcm_ptp_uint64_read(resp + i);
    567     i += 8;
    568     localTime_nsec = _bcm_ptp_uint32_read(resp + i);
    569 
    570     /* PHY synchronization. */
    571     if (0 == physync_reqd) {
    572         /* PHY synchronization is not required. */
    573         return rv;
    574     }
    575 
    576     /*
    577      * PHY synchronization.
    578      * Calculate reference phase to program PHYs.
    579      * Reference phase based on local time (i.e. when stack is queried for
    580      * PHY synchronization state) plus sufficient delta to guarantee stack
    581      * can receive and process PHY framesync at BSHB which corresponds to
    582      * programmed phase.
    583      * 
    584      * NOTE: Reference phase is quantized in microsecond to align with BSHB.
    585      *       Katana timing card PHY synchronization integrated with BSHB TS
    586      *       processing and has access to full-rate (4KHz) BSHB interrupts.
    587      *       Keystone timing card PHY synchronization integrated with BSHB
    588      *       DPLL and hass access to 1KHz timestamps for DPLL update.
    589      */
    590     physyncTime_nsec = localTime_sec;
    591     COMPILER_64_ADD_32(physyncTime_nsec, PTP_MODULAR_PHYSYNC_REFPHASE_OFFSET_SEC);
    592     COMPILER_64_UMUL_32(physyncTime_nsec, 1000000000);
    593     COMPILER_64_ADD_32(physyncTime_nsec, ((localTime_nsec+500000)/1000000)*1000000);
    594 
    595     /*
    596      * PHY synchronization.
    597      * Trigger/stage framesync.
    598      * Program reference phase.
    599      * Send framesync (FW initiated GPIO high/low @ prescribed time).
    600      */
    601     
    602     physync_input.framesync_pin = modular_options.framesync_pin > 0 ?
    603         modular_options.framesync_pin : PTP_MODULAR_PHYSYNC_FRAMESYNC_PIN;
    604     physync_input.freq_pin= PTP_MODULAR_PHYSYNC_FREQUENCY_PIN;
    605     physync_input.reference_time = physyncTime_nsec;
    606 
    607     /* Initial framesync. Pull pin low. */
    608     if (BCM_FAILURE(rv = bcm_common_ptp_sync_phy(unit, ptp_id, clock_num, physync_input))) {
    609         PTP_ERROR_FUNC("bcm_common_ptp_sync_phy()");
    610         return rv;
    611     }
    612 
    613     /* Wait. Allow initial framesync to occur. */
    614     sal_usleep(PTP_MODULAR_PHYSYNC_FRAMESYNC_WAIT_USEC);
    615 
    616     /* coverity[overrun-local] */
    617     SOC_DPORT_PBMP_ITER(unit, modular_options.pbmp, dport, p) {
    618         if (BCM_FAILURE(rv = _bcm_ptp_modular_physync_configure(unit, p, physyncTime_nsec))) {
    619             PTP_ERROR_FUNC("_bcm_ptp_modular_physync_configure()");
    620             return rv;
    621         }
    622     }
    623 
    624     /* Actual framesync. Load PHY values. */
    625     if (BCM_FAILURE(rv = bcm_common_ptp_sync_phy(unit, ptp_id, clock_num, physync_input))) {
    626         PTP_ERROR_FUNC("bcm_common_ptp_sync_phy()");
    627         return rv;
    628     }
    629     
    630     return BCM_E_NONE;
    631 }
    632 
    633 /*
    634  * Function:
    635  *      _bcm_ptp_modular_physync_configure
    636  * Purpose:
    637  *      Configure PHY port to track 4KHz SYNC_IN0 with framesync on GPIO pin.
    638  * Parameters:
    639  *      unit      - (IN) Unit number.
    640  *      port      - (IN) Port.
    641  *      ref_phase - (IN) Reference phase.
    642  * Returns:
    643  *      BCM_E_XXX - Function status.
    644  * Notes:
    645  */
    646 static int
    647 _bcm_ptp_modular_physync_configure(
    648     int unit,
    649     bcm_port_t port,
    650     uint64 ref_phase)
    651 {
    652     int rv;
    653     bcm_port_phy_timesync_config_t config;
    654     uint64 load_control;
    655 
    656     uint64 localTime;
    657 
    658     sal_memset(&config, 0, sizeof(config));
    659 
    660     config.validity_mask = BCM_PORT_PHY_TIMESYNC_VALID_FLAGS | BCM_PORT_PHY_TIMESYNC_VALID_GMODE |
    661         BCM_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE | BCM_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE |
    662         BCM_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE |
    663         BCM_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE |
    664         BCM_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE | BCM_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE |
    665         BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE |
    666         BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA |
    667         BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1 | BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2 |
    668         BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3 |
    669         BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_LOOP_FILTER;
    670 
    671     config.flags = BCM_PORT_PHY_TIMESYNC_ENABLE |
    672         BCM_PORT_PHY_TIMESYNC_L2_ENABLE |
    673         BCM_PORT_PHY_TIMESYNC_IP4_ENABLE |
    674         BCM_PORT_PHY_TIMESYNC_IP6_ENABLE |
    675         BCM_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT;
    676 
    677     config.gmode = bcmPortPhyTimesyncModeCpu;
    678     config.framesync.mode = bcmPortPhyTimesyncFramesyncSyncin1;
    679     config.syncout.mode = bcmPortPhyTimesyncSyncoutDisable;
    680     config.tx_sync_mode = bcmPortPhyTimesyncEventMessageEgressModeUpdateCorrectionField;
    681     config.rx_sync_mode = bcmPortPhyTimesyncEventMessageIngressModeUpdateCorrectionField;
    682     config.tx_delay_request_mode = bcmPortPhyTimesyncEventMessageEgressModeUpdateCorrectionField;
    683     config.rx_delay_request_mode = bcmPortPhyTimesyncEventMessageIngressModeUpdateCorrectionField;
    684     /* for 4KHz SyncIn */
    685     config.phy_1588_dpll_ref_phase = ref_phase;
    686     config.phy_1588_dpll_ref_phase_delta = 250000;
    687     config.phy_1588_dpll_k1 = 0x2b;
    688     config.phy_1588_dpll_k2 = 0x26;
    689     config.phy_1588_dpll_k3 = 0;
    690 
    691     /* Initial value for the loop filter: 0x8000 0000 0000 0000 */
    692     COMPILER_64_SET(config.phy_1588_dpll_loop_filter, 0x80000000, 0);
    693 
    694     if (BCM_FAILURE(rv = bcm_port_phy_timesync_config_set(unit, port, &config))) {
    695         PTP_ERROR_FUNC("bcm_port_phy_timesync_config_set()");
    696         return rv;
    697     }
    698 
    699     /*
    700      * Set local time (use reference phase).
    701      * NOTE: Empirically, programmed PHY timesync local time has scale factor
    702      *       of 16 compared to argument specified in nanoseconds.
    703      *       PHY data sheet mentions registers 2a,2b,2c to set 44 MSBs of PHY
    704      *       local timestamper. Control of upper 44 bits of 48-bit local time
    705      *       likely accounts for 4-bit (16x) scaling required to set the PHY
    706      *       local time with nanoseconds reference phase via following API.
    707      */
    708     localTime = _bcm_ptp_llu_div(ref_phase, 16);
    709     if (BCM_FAILURE(rv = bcm_port_control_phy_timesync_set(unit, port,
    710             bcmPortControlPhyTimesyncLocalTime, localTime))) {
    711         PTP_ERROR_FUNC("bcm_port_control_phy_timesync_set()");
    712         return rv;
    713     }
    714 
    715     COMPILER_64_SET(load_control, 0,
    716                     BCM_PORT_PHY_TIMESYNC_TN_LOAD |
    717                     BCM_PORT_PHY_TIMESYNC_TIMECODE_LOAD |
    718                     BCM_PORT_PHY_TIMESYNC_SYNCOUT_LOAD |
    719                     BCM_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD |
    720                     BCM_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD |
    721                     BCM_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD |
    722                     BCM_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD |
    723                     BCM_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD |
    724                     BCM_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD |
    725                     BCM_PORT_PHY_TIMESYNC_DPLL_K3_LOAD |
    726                     BCM_PORT_PHY_TIMESYNC_DPLL_K2_LOAD |
    727                     BCM_PORT_PHY_TIMESYNC_DPLL_K1_LOAD );
    728 
    729     /* Set load control. */
    730     if (BCM_FAILURE(rv = bcm_port_control_phy_timesync_set(unit, port,
    731             bcmPortControlPhyTimesyncLoadControl, load_control))) {
    732         PTP_ERROR_FUNC("bcm_port_control_phy_timesync_set()");
    733         return rv;
    734     }
    735 
    736     return BCM_E_NONE;
    737 }
    738 
    739 #endif /* defined(INCLUDE_PTP) */