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

bs.c (17439B)


      1 /*
      2  * 
      3  *
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  */
      8 
      9 #include <bcm/error.h>
     10 #include <bcm/time.h>
     11 #include <shared/bsl.h>
     12 #include <appl/diag/system.h>
     13 #include <appl/diag/parse.h>
     14 
     15 #ifdef NO_SAL_APPL
     16 #include <string.h>
     17 #else
     18 #include <sal/appl/sal.h>
     19 #endif
     20 
     21 #ifdef BCM_CMICM_SUPPORT
     22 
     23 #include <bcm_int/esw/port.h>
     24 #include <bcm_int/common/mbox.h>
     25 #include <bcm_int/common/time.h>
     26 #include <bcm_int/common/time-mbox.h>
     27 #include <include/soc/uc.h>
     28 #if defined(INCLUDE_PTP)
     29 extern int _bcm_ptp_running(int unit);
     30 #endif /* INCLUDE_PTP */
     31 
     32 /* A sentinel value to indicate that no valid value was passed in */
     33 /* static int64 ILLEGAL_OFFSET_LL = COMPILER_64_INIT(0x7fffffff, 0xffffffff); */
     34 static uint32 ILLEGAL_OFFSET = 0x7fffffff;
     35 
     36 #define BS_NANOSECONDS_PER_SECOND (1000000000)
     37 
     38 #define CLEAN_UP_AND_RETURN(_result)            \
     39     parse_arg_eq_done(&parse_table);            \
     40     return (_result);
     41 
     42 #define _isprintable(_c) (((_c) > 32) && ((_c) < 127))
     43 
     44 char cmd_broadsync_usage[] =
     45 #ifdef COMPILER_STRING_CONST_LIMIT
     46     "Usage: BroadSync <option> [args...]\n"
     47 #else
     48     "\n"
     49     "  BroadSync CONFig [Master] [BitClock=<hz>] [HeartBeat=<hz>] [Freq=<ppb offset>] [PhaseSec=<seconds>] [PhaseNSec]=<nanoseconds>\n"
     50     "                   [NtpSec=<seconds>] [NtpNSec]=<nanoseconds> [BSTimeSec=<seconds>] \n"
     51     "    Initialize or reconfigure.  Default is slave, if 'Master' is not specified\n"
     52     "  BroadSync STATus\n"
     53     "    Show DPLL lock state\n"
     54     "  BroadSync 1PPS [ON|OFF]\n"
     55     "    No option: print 1PPS state.  ON/OFF: enable/disable 1PPS output\n"
     56     "  BroadSync DEBUG [ON|OFF]\n"
     57     "    No option: print debug state.  ON/OFF: enable/disable debug output\n"
     58     "  BroadSync LOG [LogDebug] [LogPLL] [Vlan=<vlan>] [DestMAC=<mac>] [DestAddr=<addr>] [SrcMAC=<mac>] [SrcAddr=<addr>] [UDPPort=<udp port>]\n"
     59     "    Sets UDP logging state\n"
     60     "  BroadSync CLEANUP\n"
     61     "    Cleanup the interface\n"
     62 #endif
     63     ;
     64 
     65 typedef struct {
     66     bcm_time_if_t   bs_id;
     67     int             bs_initialized;
     68 } _bcm_time_intf_info;
     69 
     70 int _bcm_time_interface_traverse_cb(int unit, bcm_time_interface_t *intf, void *user_data)
     71 {
     72     _bcm_time_intf_info *bstime_intf_info = (_bcm_time_intf_info*)user_data;
     73     if (intf->flags & BCM_TIME_SYNC_STAMPER) {
     74         bstime_intf_info->bs_id = intf->id;
     75         bstime_intf_info->bs_initialized = 1;
     76     }
     77     return (BCM_E_NONE);
     78 }
     79 
     80 cmd_result_t cmd_broadsync(int unit, args_t *args)
     81 {
     82     char *arg_string_p = NULL;
     83     int result;
     84     _bcm_time_intf_info bstime_intf_info;
     85 
     86 
     87     int arg_is_master = 0, arg_nophase = 0;
     88 
     89     /* Check to verify Broadsync Firmware is present */
     90     int uc;
     91     char *version = NULL;
     92     int bs_fw = 0;
     93     for(uc=0; uc<SOC_INFO(unit).num_ucs; uc++) {
     94         if (!soc_uc_in_reset(unit, uc)) {
     95             version = soc_uc_firmware_version(unit, uc);
     96             if (version) {
     97 #ifdef NO_SAL_APPL
     98                 if (strstr((char *)version,(char *)"BS")) {
     99 #else
    100                 if (sal_strcasestr((char *)version,(char *)"BS")) {
    101 #endif
    102                     bs_fw = 1;
    103                 }
    104 
    105                 soc_cm_sfree(unit, version);
    106                 if (1 == bs_fw) {
    107                     break;
    108                 }
    109             }
    110         }
    111     }
    112     if (bs_fw == 0) {
    113         cli_out("Failed: Broadsync firmware not loaded\n");
    114         return CMD_FAIL;
    115     }
    116 
    117     arg_string_p = ARG_GET(args);
    118 
    119     if (arg_string_p == NULL) {
    120         return CMD_USAGE;
    121     }
    122 
    123     if (!sh_check_attached(ARG_CMD(args), unit)) {
    124         return CMD_FAIL;
    125     }
    126 
    127     bstime_intf_info.bs_id = 0;
    128     bstime_intf_info.bs_initialized = 0;
    129 
    130     bcm_time_interface_traverse(unit, _bcm_time_interface_traverse_cb,
    131                                 (void*)&bstime_intf_info);
    132 
    133     if (parse_cmp("CONFig", arg_string_p, 0)) {
    134         parse_table_t parse_table;
    135         int n_args = 0;
    136         bcm_time_interface_t intf;
    137         int32 freq = ILLEGAL_OFFSET;
    138         int32 phase_sec = ILLEGAL_OFFSET;
    139         int32 phase_nsec = ILLEGAL_OFFSET;
    140         uint32 bs_time_sec = 0;
    141         uint32 ntp_sec = 0;
    142         uint32 ntp_nsec = 0;
    143 
    144         if (bstime_intf_info.bs_initialized) {
    145             intf.id = bstime_intf_info.bs_id;
    146             intf.flags = BCM_TIME_OFFSET | BCM_TIME_DRIFT |
    147                 BCM_TIME_REF_CLOCK | BCM_TIME_HEARTBEAT;
    148             bcm_time_interface_get(unit, &intf);
    149 
    150             intf.flags = BCM_TIME_WITH_ID | BCM_TIME_REPLACE |
    151                 BCM_TIME_ENABLE | BCM_TIME_SYNC_STAMPER |
    152                 BCM_TIME_REF_CLOCK | BCM_TIME_HEARTBEAT;
    153         } else {
    154 #if defined(INCLUDE_PTP)
    155              if (_bcm_ptp_running(unit) != BCM_E_NONE) {
    156 #endif /* INCLUDE_PTP */
    157                 /* Check for BS firmware on the unit */
    158                 result = _bcm_mbox_comm_init(unit, MOS_MSG_MBOX_APPL_BS);
    159                 if (BCM_FAILURE(result)) {
    160                     cli_out("Broadsync MBox Communication FAILED!!\n");
    161                     return CMD_FAIL;
    162                 }
    163 #if defined(INCLUDE_PTP)
    164             }
    165 #endif /* INCLUDE_PTP */
    166 
    167             intf.flags = BCM_TIME_ENABLE | BCM_TIME_SYNC_STAMPER |
    168                 BCM_TIME_REF_CLOCK | BCM_TIME_HEARTBEAT;
    169 
    170             intf.id = 0;                                    /* Time Interface Identifier */
    171             intf.drift.isnegative = 0;                      /* Drift amount per 1 Sec */
    172             COMPILER_64_ZERO(intf.drift.seconds);
    173             intf.drift.nanoseconds = 0;
    174             intf.offset.isnegative = 0;                     /* Offset */
    175             COMPILER_64_ZERO(intf.offset.seconds);
    176             intf.offset.nanoseconds = 0;
    177             intf.accuracy.isnegative = 0;                   /* Accuracy */
    178             COMPILER_64_ZERO(intf.accuracy.seconds);
    179             intf.accuracy.nanoseconds = 0;
    180             intf.clk_resolution = 1;                        /* Reference clock resolution in nsecs */
    181 
    182             intf.bitclock_hz = 10000000;  /* 10MHz default bitclock */
    183             intf.heartbeat_hz = 4000;     /* 4KHz default heartbeat */
    184         }
    185 
    186         intf.flags &= ~(BCM_TIME_DRIFT);
    187         intf.flags &= ~(BCM_TIME_OFFSET);
    188         intf.flags &= ~(BCM_TIME_BS_TIME);
    189 
    190         parse_table_init(unit, &parse_table);
    191 
    192         parse_table_add(&parse_table, "Master", PQ_DFL | PQ_BOOL | PQ_NO_EQ_OPT, (void*)0, &arg_is_master, NULL);
    193         parse_table_add(&parse_table, "BitClock", PQ_DFL | PQ_INT, NULL, &intf.bitclock_hz, NULL);
    194         parse_table_add(&parse_table, "HeartBeat", PQ_DFL | PQ_INT, NULL, &intf.heartbeat_hz, NULL);
    195         parse_table_add(&parse_table, "Freq", PQ_DFL | PQ_INT, NULL, &freq, NULL);
    196         parse_table_add(&parse_table, "PhaseSec", PQ_DFL | PQ_INT, NULL, &phase_sec, NULL);
    197         parse_table_add(&parse_table, "PhaseNSec", PQ_DFL | PQ_INT, NULL, &phase_nsec, NULL);
    198         parse_table_add(&parse_table, "NoPhase", PQ_DFL | PQ_BOOL | PQ_NO_EQ_OPT, (void*)0, &arg_nophase, NULL);
    199         parse_table_add(&parse_table, "NtpSec", PQ_DFL | PQ_INT, NULL, &ntp_sec, NULL);
    200         parse_table_add(&parse_table, "NtpNSec", PQ_DFL | PQ_INT, NULL, &ntp_nsec, NULL);
    201         parse_table_add(&parse_table, "BSTimeSec", PQ_DFL | PQ_INT, NULL, &bs_time_sec, NULL);
    202         /* When PTP is running, "NoPhase" can be used to indicate that the servo phase should be ignored
    203          * i.e. that the BroadSync time should be the timestamper time, not PTP time, by clearing REF_CLOCK
    204          */
    205 
    206         n_args = parse_arg_eq(args, &parse_table);
    207 
    208         if ((n_args < 0) || (ARG_CNT(args) > 0)) {
    209             cli_out("Invalid option: %s\n", ARG_CUR(args));
    210             CLEAN_UP_AND_RETURN(CMD_USAGE);
    211         }
    212 
    213         if (!arg_is_master) {
    214             intf.flags |= BCM_TIME_INPUT;
    215         }
    216 
    217         if (arg_nophase) {
    218             intf.flags &= ~BCM_TIME_REF_CLOCK;
    219         }
    220 
    221         if (freq != ILLEGAL_OFFSET) {
    222             intf.flags |= BCM_TIME_DRIFT;
    223             intf.drift.isnegative = (freq < 0) ? 1 : 0;
    224             COMPILER_64_ZERO(intf.drift.seconds);
    225             freq = (freq < 0) ? (-freq) : (freq);
    226             intf.drift.nanoseconds = (uint32) freq;
    227         }
    228 
    229         if ((phase_sec != ILLEGAL_OFFSET) || (phase_nsec != ILLEGAL_OFFSET)) {
    230             /* Valid seconds or nanoseconds component of phase offset. */
    231             intf.flags |= BCM_TIME_OFFSET;
    232 
    233             phase_sec = (phase_sec == ILLEGAL_OFFSET) ? 0 : phase_sec;
    234             phase_nsec = (phase_nsec == ILLEGAL_OFFSET) ? 0 : phase_nsec; 
    235 
    236             /* Discard integer seconds, if any,  from nanoseconds term. */
    237             while (phase_nsec >= BS_NANOSECONDS_PER_SECOND) {
    238                 phase_nsec -= BS_NANOSECONDS_PER_SECOND;
    239             } 
    240             while (phase_nsec <= -BS_NANOSECONDS_PER_SECOND) {
    241                 phase_nsec += BS_NANOSECONDS_PER_SECOND;
    242             } 
    243 
    244             /* Reconcile different signs in seconds and nanoseconds terms. */
    245             if (phase_sec > 0 && phase_nsec < 0) {
    246                 --phase_sec;
    247                 phase_nsec += BS_NANOSECONDS_PER_SECOND;
    248             } else if (phase_sec < 0 && phase_nsec > 0) {
    249                 ++phase_sec;
    250                 phase_nsec -= BS_NANOSECONDS_PER_SECOND;
    251             }
    252 
    253             intf.offset.isnegative = ((phase_sec < 0) || (phase_nsec < 0)) ? 1 : 0;
    254             phase_sec = (intf.offset.isnegative) ? (-phase_sec) : (phase_sec);
    255             phase_nsec = (intf.offset.isnegative) ? (-phase_nsec) : (phase_nsec);
    256 
    257             COMPILER_64_SET(intf.offset.seconds, 0, ((uint32)phase_sec));
    258             intf.offset.nanoseconds = (uint32) phase_nsec;
    259         } else {
    260             /* Invalid seconds and nanoseconds component of phase offset. */
    261             intf.flags &= ~(BCM_TIME_OFFSET);
    262         }
    263 
    264         if (bs_time_sec != 0) {
    265             /* Valid seconds or nanoseconds component */
    266             intf.flags |= BCM_TIME_BS_TIME;
    267 
    268             intf.bs_time.isnegative = 0;
    269             COMPILER_64_SET(intf.bs_time.seconds, 0, bs_time_sec);
    270             intf.bs_time.nanoseconds = 0;
    271         } else {
    272             /* Invalid seconds and nanoseconds component . */
    273             intf.flags &= ~(BCM_TIME_BS_TIME);
    274         }
    275 
    276         if (ntp_sec != 0) {
    277             intf.flags |= BCM_TIME_NTP_OFFSET;
    278             
    279             while (ntp_nsec >= BS_NANOSECONDS_PER_SECOND) {
    280                 ntp_nsec -= BS_NANOSECONDS_PER_SECOND;
    281             } 
    282 
    283             /*ntp offset is always positive*/
    284             intf.ntp_offset.isnegative = 0;
    285             COMPILER_64_SET(intf.ntp_offset.seconds, 0, ntp_sec);
    286             intf.ntp_offset.nanoseconds = ntp_nsec;
    287         } else {
    288             intf.flags &= ~(BCM_TIME_NTP_OFFSET);
    289         }
    290 
    291         result = bcm_time_interface_add(unit, &intf);
    292         if (BCM_FAILURE(result)) {
    293             cli_out("Command failed. %s\n", bcm_errmsg(result));
    294             CLEAN_UP_AND_RETURN(CMD_FAIL);
    295         }
    296                     
    297         CLEAN_UP_AND_RETURN(CMD_OK);
    298 
    299     } else if (parse_cmp("reattach", arg_string_p, 0)) {
    300 
    301         if (!bstime_intf_info.bs_initialized) {
    302             cli_out("BroadSync not initialized on unit %d\n", unit);
    303             return CMD_FAIL;
    304         }
    305 
    306         /* Reattach BS firmware on the unit */
    307         result = _bcm_mbox_comm_init(unit, MOS_MSG_MBOX_APPL_BS);
    308         if (BCM_FAILURE(result)) {
    309             cli_out("Broadsync reattach FAILED\n");
    310             return CMD_FAIL;
    311         }
    312 
    313         cli_out("BroadSync FW reattached on unit %d\n", unit);
    314 
    315     } else if (parse_cmp("STATus", arg_string_p, 0)) {
    316         int status = 0;
    317 
    318         if (!bstime_intf_info.bs_initialized) {
    319             cli_out("BroadSync not initialized on unit %d\n", unit);
    320             return CMD_FAIL;
    321         }
    322 
    323         arg_string_p = ARG_GET(args);
    324 
    325         if (arg_string_p != NULL) {
    326             return CMD_USAGE;
    327         }
    328 
    329         _bcm_time_bs_status_get(0, &status);
    330 
    331         cli_out("Status = %d\n", status);
    332     } else if (parse_cmp("wb", arg_string_p, 0)) {
    333 
    334         /* Send the message to BS-FW about warmboot */
    335         cli_out("Warmboot prep on BroadSync FW for unit %d\n",
    336                 unit);
    337 
    338         if (!bstime_intf_info.bs_initialized) {
    339             cli_out("BroadSync not initialized on unit %d\n", unit);
    340             return CMD_FAIL;
    341         }
    342 
    343         arg_string_p = ARG_GET(args);
    344         if (NULL != arg_string_p) {
    345             return CMD_USAGE;
    346         }
    347 
    348         if (BCM_E_NONE != _bcm_mbox_bs_wb_prep(unit)) {
    349             cli_out("BroadSync-FW warmboot prep failed!! \n");
    350             return CMD_FAIL;
    351         }
    352     } else if (parse_cmp("1PPS", arg_string_p, 0)) {
    353         if (!bstime_intf_info.bs_initialized) {
    354             cli_out("BroadSync not initialized on unit %d\n", unit);
    355             return CMD_FAIL;
    356         }
    357 
    358         arg_string_p = ARG_GET(args);
    359 
    360         if (arg_string_p == NULL) {
    361             int enabled;
    362 
    363             if (BCM_FAILURE(bcm_time_heartbeat_enable_get(unit, bstime_intf_info.bs_id, &enabled))) {
    364                 cli_out("Error getting heartbeat (1pps) enable status\n");
    365                 return CMD_FAIL;
    366             } else {
    367                 cli_out("1PPS is %s\n", (enabled) ? "Enabled" : "Disabled");
    368                 return CMD_OK;
    369             }
    370         }
    371 
    372         if (parse_cmp(arg_string_p, "ON", 0)) {
    373             result = bcm_time_heartbeat_enable_set(unit, bstime_intf_info.bs_id, 1);
    374         } else if (parse_cmp(arg_string_p, "OFF", 0)) {
    375             result = bcm_time_heartbeat_enable_set(unit, bstime_intf_info.bs_id, 0);
    376         } else {
    377             return CMD_USAGE;
    378         }
    379 
    380         if (BCM_FAILURE(result)) {
    381             cli_out("Command failed. %s\n", bcm_errmsg(result));
    382             return CMD_FAIL;
    383         }
    384 
    385     } else if (parse_cmp("DEBUG", arg_string_p, 0)) {
    386 
    387         if (!bstime_intf_info.bs_initialized) {
    388             cli_out("BroadSync not initialized on unit %d\n", unit);
    389             return CMD_FAIL;
    390         }
    391 
    392         arg_string_p = ARG_GET(args);
    393 
    394         if (arg_string_p == NULL) {
    395             uint32 flags;
    396             if (BCM_FAILURE(_bcm_mbox_debug_flag_get(&flags))) {
    397                 cli_out("Error getting debug status\n");
    398             } else {
    399                 cli_out("Debug output is %s\n", (flags) ? "On" : "Off");
    400                 return CMD_OK;
    401             }
    402         }
    403 
    404         if (parse_cmp("ON", arg_string_p, 0)) {
    405             _bcm_mbox_debug_flag_set(0xff);
    406         } else if (parse_cmp(arg_string_p, "OFF", 0)) {
    407             _bcm_mbox_debug_flag_set(0);
    408         } else {
    409             return CMD_USAGE;
    410         }
    411 
    412     } else if (parse_cmp("LOG", arg_string_p, 0)) {
    413         parse_table_t parse_table;
    414         int arg_log_debug = 0;
    415         int arg_log_pll = 0;
    416         bcm_mac_t dest_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /* default to broadcast */
    417         bcm_mac_t src_mac = {0x00, 0x10, 0x18, 0x00, 0x00, 0x01};
    418         bcm_ip_t dest_ip = 0xffffffff; /* default to broadcast */
    419         bcm_ip_t src_ip = (192L << 24) + (168L << 16) +(0L << 8) + 90;
    420         int udp_port = 0x4455;
    421         int tpid = 0x8100;
    422         int vlan = 1;
    423         int ttl = 1;
    424         uint64 udp_log_mask = COMPILER_64_INIT(0,0);
    425         uint64 log_debug_bit = COMPILER_64_INIT(0,0x01);
    426         uint64 log_pll_bit = COMPILER_64_INIT(0,0x40);
    427 
    428         int rv = 0;
    429 
    430         if (!bstime_intf_info.bs_initialized) {
    431             cli_out("BroadSync not initialized on unit %d\n", unit);
    432             return CMD_FAIL;
    433         }
    434 
    435         parse_table_init(unit, &parse_table);
    436 
    437         parse_table_add(&parse_table, "LogDebug", PQ_DFL | PQ_BOOL | PQ_NO_EQ_OPT, (void*)0, &arg_log_debug, NULL);
    438         parse_table_add(&parse_table, "LogPLL", PQ_DFL | PQ_BOOL | PQ_NO_EQ_OPT, (void*)0, &arg_log_pll, NULL);
    439         parse_table_add(&parse_table, "DestMAC", PQ_DFL | PQ_MAC, NULL, dest_mac, NULL);
    440         parse_table_add(&parse_table, "DestAddr", PQ_DFL | PQ_IP, NULL, &dest_ip, NULL);
    441         parse_table_add(&parse_table, "SrcMAC", PQ_DFL | PQ_MAC, NULL, src_mac, NULL);
    442         parse_table_add(&parse_table, "SrcAddr", PQ_DFL | PQ_IP, NULL, &src_ip, NULL);
    443         parse_table_add(&parse_table, "UDPPort", PQ_DFL | PQ_INT, NULL, &udp_port, NULL);
    444         parse_table_add(&parse_table, "Vlan", PQ_DFL | PQ_INT, NULL, &vlan, NULL);
    445 
    446         if (parse_arg_eq(args, &parse_table) < 0) {
    447             cli_out("%s: Invalid option %s\n", ARG_CMD(args), ARG_CUR(args));
    448         }
    449 
    450         if (arg_log_debug) {
    451             COMPILER_64_OR(udp_log_mask, log_debug_bit);
    452         }
    453         if (arg_log_pll) {
    454             COMPILER_64_OR(udp_log_mask, log_pll_bit);
    455         }
    456 
    457         rv = _bcm_time_bs_log_configure(unit, 0xff, udp_log_mask,
    458                                         src_mac, dest_mac, tpid, vlan, ttl,
    459                                         src_ip, dest_ip, udp_port);
    460         
    461         if (rv != BCM_E_NONE) {
    462             cli_out("Failed setting log configuration: %s\n", bcm_errmsg(rv));
    463             return CMD_FAIL;
    464         }
    465     } else if (parse_cmp("CLEANUP", arg_string_p, 0)) {
    466         if (bstime_intf_info.bs_initialized) {
    467             cli_out("Broadsync cleanup\n");
    468             result = bcm_time_interface_delete(unit, bstime_intf_info.bs_id);
    469             if (BCM_FAILURE(result)) {
    470                 cli_out("Command failed. %s\n", bcm_errmsg(result));
    471                 return CMD_FAIL;
    472             }
    473             return CMD_OK;
    474         }
    475     } else {
    476         return CMD_USAGE;
    477     }
    478 
    479     return CMD_OK;
    480 }
    481 
    482 #endif