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