gdpll.c (77495B)
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: gdpll.c 8 * Purpose: GDPLL diag shell commands 9 */ 10 11 #include <bcm/error.h> 12 #include <bcm/gdpll.h> 13 #include <bcm/time.h> 14 #include <bcm_int/esw/gdpll.h> 15 #include <shared/bsl.h> 16 #include <appl/diag/system.h> 17 #include <appl/diag/parse.h> 18 #ifdef CPRIMOD_SUPPORT 19 #include <soc/cprimod/cprif_drv.h> 20 #endif 21 #include <soc/iproc.h> 22 23 #ifdef NO_SAL_APPL 24 #include <string.h> 25 #else 26 #include <sal/appl/sal.h> 27 #endif 28 29 #ifdef INCLUDE_GDPLL 30 31 #include <bcm_int/esw/port.h> 32 #include <include/soc/uc.h> 33 #if defined(UNIX) && !defined(__KERNEL__) 34 #include <time.h> 35 #define GDPLL_SAL_HAS_TIME (1) 36 #endif 37 38 char cmd_gdpll_usage[] = 39 #ifdef COMPILER_STRING_CONST_LIMIT 40 "Usage: GDPLL <option> [args...]\n" 41 #else 42 "\n" 43 "gdpll chan create <config_filename>\n" 44 " Create the DPLL channel\n" 45 " UseCase-1A: gdpll chan create <dpll_1A_xxx.config> [SyncBS0HB/SyncBS1HB/SyncGPIO2]\n" 46 " UseCase-1G: gdpll chan create <dpll_1G_xxx.config> [SyncGPSToD]\n" 47 " Ensure to define use_case_flag in config as per the bellow table\n" 48 " use_case_flag:1 UseCase-1A\n" 49 " use_case_flag:2 UseCase-1E\n" 50 " use_case_flag:3 UseCase-1D\n" 51 " use_case_flag:4 UseCase-1G\n" 52 " use_case_flag:5 UseCase-2D\n" 53 " use_case_flag:6 UseCase-BS_Synthesizer\n" 54 " use_case_flag:7 UseCase-1N\n" 55 " use_case_flag:8 UseCase-1P\n" 56 "gdpll flush\n" 57 " Flush GDPLL\n" 58 "gdpll Rsvd1cbreg\n" 59 " Register callback for RSVD1 message\n" 60 "gdpll Rsvd1cbunreg\n" 61 " Un-register callback for RSVD1 message\n" 62 "gdpll debug <enable:0/1> <file_name/UDP> [DestMAC=<mac>] [DestAddr=<addr>] [SrcMAC=<mac>] [SrcAddr=<addr>] [UDPSrcPort=< port>] [UDPDestPort=< port>] [VLan=<vlan>] [TTL=<ttl>]" 63 " Set the GDPLL debug feature\n" 64 "gdpll chan destroy <chan_num>\n" 65 " Destroy the DPLL channel\n" 66 "gdpll chan enable <chan_num>\n" 67 " Enable the DPLL channel\n" 68 "gdpll chan disable <chan_num>\n" 69 " Disable the the DPLL channel\n" 70 "gdpll chan monitor <chan_num>\n" 71 " Monitor the channel status\n" 72 "gdpll chan dump <chan_num>\n" 73 " Dump the channel debug info\n" 74 "gdpll chan status <chan_num>\n" 75 " Get the status of DPLL channel\n" 76 " Bit-31 ChannelError status\n" 77 " Bit-30 LargeErrorIndicator\n" 78 " Bit-8 ChannelEnable Status\n" 79 " Bit-7:1 LossOfLockIndicator Count\n" 80 " Bit-0 Channel LockIndicator\n" 81 "gdpll chan debug <chan_num> <debugMode>\n" 82 " Set the debug mode for a given channel\n" 83 " Mode:0 Channel debug logging Disbaled, closed-loop\n" 84 " Mode:1 Channel debug logging(record bellow, each 64b) in closed-loop\n" 85 " Mode:2 Channel debug logging(record bellow, each 64b) in open-loop\n" 86 " <Channel_num+ChannelState>, <FB-TS>, <REF-TS>, <PERROR>, <NCO>, <LoopFilter>, <LockDetFilter>\n" 87 " Mode:3 Channel debug logging(record bellow, each 64b) in open-loop\n" 88 " <FB-TS>\n" 89 "gdpll offset <set/get> <chan_num> <offset_H> <offset_L>\n" 90 " offset_H/L - 32b/32b with LS:4b are sub-ns\n" 91 #endif 92 ; 93 94 extern int _bcm_esw_get_timestamp(int unit, int timestamper, uint64 *pTs_52); 95 extern int _bcm_esw_timestamp_enable(int unit, int timestamper, int enable); 96 extern int _bcm_esw_set_timestamp(int unit, int timestamper, uint64 ts_52); 97 extern int _bcm_esw_gdpll_offset_set(int unit, int chan, uint64 Offset); 98 extern int _bcm_esw_gdpll_offset_get(int unit, int chan, uint64 *pOffset); 99 100 static int debug_enable_flag = 0; 101 static int use_case_flag = 0; 102 static int disable_debug_log = 0; 103 static int port_out; 104 105 typedef struct gdpll_app_context_s { 106 int chan_status[BCM_GDPLL_NUM_CHANNELS]; 107 int chan_mon_flag[BCM_GDPLL_NUM_CHANNELS]; 108 } gdpll_app_context_t; 109 gdpll_app_context_t *pGdpllAppContext = NULL; 110 111 #ifndef NO_FILEIO 112 FILE * volatile fp = NULL; 113 #endif 114 115 #define GPS_ToD_DEMO 116 117 #ifdef GPS_ToD_DEMO 118 #define ToD_BUFFER_LENGTH 40 119 #define ToD_LOCATION 0x0127FF80 /* Monterey msg_base:0x0127f000, 4KB */ 120 #define ToD_LOCATION_AVAIL 0x0127FFFC 121 122 #ifdef GDPLL_SAL_HAS_TIME 123 time_t time_to_epoch ( const struct tm *ltm, int utcdiff ) 124 { 125 const int mon_days [] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 126 long tyears, tdays, leaps, utc_hrs; 127 int i; 128 129 tyears = ltm->tm_year - 70 ; /* tm->tm_year is from 1900. */ 130 leaps = (tyears + 2) / 4; /* no of next two lines until year 2100. */ 131 /*i = (ltm->tm_year - 100) / 100; */ 132 /*leaps -= ( (i/4)*3 + i%4 ); */ 133 tdays = 0; 134 for (i=0; i < ltm->tm_mon; i++) 135 tdays += mon_days[i]; 136 137 tdays += ltm->tm_mday-1; /* days of month passed. */ 138 tdays = tdays + (tyears * 365) + leaps; 139 utc_hrs = ltm->tm_hour + utcdiff; /* for your time zone. */ 140 return (tdays * 86400) + (utc_hrs * 3600) + (ltm->tm_min * 60) + ltm->tm_sec; 141 } 142 143 void str_to_tm ( char *mdate, char *mtime, struct tm* mtm ) 144 { 145 char *pstr; 146 long year, month, day, hour, min, sec; 147 148 year = strtol( mdate, &pstr, 10 ); 149 month = strtol( ++pstr, &pstr, 10 ); 150 day = strtol( ++pstr, &pstr, 10 ); 151 152 hour = strtol( mtime, &pstr, 10 ); 153 while( !isdigit(*pstr) ) 154 ++pstr; 155 min = strtol( pstr, &pstr, 10 ); 156 while( !isdigit(*pstr) ) 157 ++pstr; 158 sec = strtol( pstr, &pstr, 10 ); 159 mtm->tm_sec = sec; 160 mtm->tm_min = min; 161 mtm->tm_hour = hour; 162 mtm->tm_mday = day; 163 mtm->tm_mon = month - 1; 164 mtm->tm_year = year - 1900; 165 } 166 167 time_t get_time(char *mydate, char *mytime) 168 { 169 struct tm mtm; 170 time_t mytcks; 171 /* time_t ticks; */ 172 173 str_to_tm ( mydate, mytime, &mtm ); 174 mytcks = time_to_epoch ( &mtm, 5 ); 175 /* ticks = mktime ( &mtm ); */ 176 #if 0 177 cli_out ( " std func time : %s", asctime(localtime(&ticks))); 178 cli_out ( " our func time : %s", asctime(localtime(&mytcks))); 179 cli_out ( " stdlib func ticks : %ld \n", ticks ); 180 cli_out ( " our func ticks : %ld \n", mytcks ); 181 #endif 182 return mytcks; 183 } 184 #endif /* GDPLL_SAL_HAS_TIME */ 185 #endif /* GPS_ToD_DEMO */ 186 187 int gdpll_debug_cb(int unit, void *user_data, uint32 debug_buff, uint32 debug_buf_size) 188 { 189 int rv = BCM_E_NONE; 190 191 #ifndef NO_FILEIO 192 int i; 193 uint32 val; 194 uint32 rd_addr = debug_buff;; 195 196 /* Write the debug buffer to a file registered */ 197 if (fp) { 198 for (i=0; i<debug_buf_size; i++, rd_addr+=4) { 199 val = soc_cm_iproc_read(unit, rd_addr); 200 if (sal_fwrite(&val,4, 1, fp) != 1) { 201 cli_out("Error writing to file\n"); 202 rv = BCM_E_FAIL; 203 } 204 } 205 } 206 #endif 207 208 return rv; 209 } 210 211 bcm_mac_t dest_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /* default to broadcast */ 212 bcm_mac_t src_mac = {0x00, 0x10, 0x18, 0x00, 0x00, 0x01}; 213 int vlan = 1; 214 /* Simple IPv4 UDP header */ 215 uint8 L3_header[] = { 216 0x08, 0x00, /* ethertype: IPv4 */ 217 0x45, 0x00, /* version, hdr len, ECN */ 218 0x00, 0x00, /* length */ 219 0x00, 0x00, /* ident = 0 */ 220 0x00, 0x00, 0x40, 0x11, /* flags = 0, fragment = 0, TTL = 64, type = UDP */ 221 0x00, 0x00, /* header checksum */ 222 192, 168, 100, 100, /* source IP */ 223 0xff, 0xff, 0xff, 0xff, /* dest IP (broadcast) */ 224 0x44, 0x55, 0x44, 0x55, /* src/dest UDP ports */ 225 0x00, 0x00, 0x00, 0x00, /* length(0), checksum (0) */ 226 }; 227 228 void 229 gdpll_channel_monitor_thread(void *unit_vp) 230 { 231 int count = 0; 232 uint32 status = 0; 233 int result; 234 int unit = PTR_TO_INT(unit_vp); 235 236 while (1) { 237 sal_usleep(1000*1000); /* Poll evenry second */ 238 for (count = 0; count < 8/*BCM_GDPLL_NUM_CHANNELS*/; count++) { 239 /* Check enable status of the channel, 0x100 */ 240 if (pGdpllAppContext && pGdpllAppContext->chan_mon_flag[count]) { 241 result = bcm_gdpll_chan_state_get(unit, count, &status); 242 if (BCM_FAILURE(result)) { 243 continue; 244 } 245 246 if (status != pGdpllAppContext->chan_status[count]) { 247 cli_out("GDPLL DIAG: Channel:%d\n", count); 248 cli_out(" Current State(%d): 0x%x\n", count, status); 249 cli_out(" Previous State(%d): 0x%x\n", count, pGdpllAppContext->chan_status[count]); 250 pGdpllAppContext->chan_status[count] = status; 251 } 252 } 253 } 254 } 255 } 256 257 int gdpll_debug_udp_cb(int unit, void *user_data, uint32 debug_buff, uint32 debug_buf_size) 258 { 259 int rv = BCM_E_NONE; 260 261 262 const int L3_header_len = sizeof(L3_header); 263 uint32 len = (debug_buf_size * 4) + L3_header_len + BCM_IEEE_HDR_BYTES + 4; /* Pkt Hdr + L3 Hdr + CRC */ 264 uint32 rd_addr = debug_buff; 265 bcm_pkt_t *txPkt; 266 uint8 *myData; 267 uint32 *myPayload; 268 int packet_len; 269 int i; 270 271 BCM_IF_ERROR_RETURN(bcm_pkt_alloc(unit, len, BCM_TX_CRC_REGEN | BCM_TX_ETHER, &txPkt)); 272 273 BCM_PKT_HDR_SMAC_SET(txPkt, src_mac); 274 BCM_PKT_HDR_DMAC_SET(txPkt, dest_mac); 275 BCM_PKT_HDR_TPID_SET(txPkt, 0x8100); 276 BCM_PKT_HDR_VTAG_CONTROL_SET(txPkt, vlan); 277 278 /* Get a pointer to the payload area of packet */ 279 if ((BCM_E_NONE == 280 bcm_pkt_byte_index(txPkt, BCM_IEEE_HDR_BYTES, &packet_len, NULL, &myData)) 281 && (myData != 0)) { 282 /* Initialize payload (IPv4/UDP header) */ 283 for (i = 0; i < L3_header_len; i++) { 284 myData[i] = L3_header[i]; 285 } 286 myPayload = (uint32 *)&myData[L3_header_len]; 287 /* Initialize rest of packet (size less FCS) */ 288 for (i=0; i<debug_buf_size; i++, rd_addr+=4) { 289 myPayload[i] = soc_cm_iproc_read(unit, rd_addr); 290 } 291 } 292 rv = bcm_tx(unit, txPkt, NULL); 293 bcm_pkt_free(unit, txPkt); 294 return rv; 295 } 296 297 void print_ts(int unit) 298 { 299 uint32 l, u; 300 soc_iproc_getreg(unit, 0x0326c088/*NS_TIMESYNC_TS1_TIMESTAMP_UPPER_STATUSr*/, &u); 301 soc_iproc_getreg(unit, 0x0326c084/*NS_TIMESYNC_TS1_TIMESTAMP_LOWER_STATUSr*/, &l); 302 303 cli_out(" u:0x%x, l:0x%x\n", u, l); 304 } 305 306 /* 307 * RSVD1 Callback function for sanity test 308 */ 309 static int rsvd1count = 0; 310 static int bcn_update = 0; 311 static int ts_update = 0; 312 static uint64 ts52b; 313 314 int bcm_gdpll_cb_rsvd1(int unit, void *user_data, uint32 *cb_data, int cb_type) 315 { 316 int rv = BCM_E_NONE; 317 318 /* cli_out(" ######## bcm_gdpll_cb_rsvd1\n"); */ 319 320 /* Following if statement is to sanity test the RSVD1 intf */ 321 if (rsvd1count) { 322 rsvd1count--; 323 cli_out(" RSVD1 stat0:0x%x\n", *cb_data); cb_data++; 324 cli_out(" RSVD1 stat1:0x%x\n", *cb_data); cb_data++; 325 cli_out(" RSVD1 stat2:0x%x\n", *cb_data); 326 327 if (rsvd1count == 0) { 328 rv = bcm_gdpll_cb_unregister(unit, BCM_GDPLL_CB_RSVD1); 329 if (BCM_FAILURE(rv)) { 330 return CMD_FAIL; 331 } 332 } 333 } 334 335 if (bcn_update || ts_update) { 336 uint32 /*rsvd1_stat0,*/ rsvd1_stat1, rsvd1_stat2; 337 uint64 N1; 338 /*uint32 N2;*/ 339 340 /*rsvd1_stat0 = *cb_data; */ 341 cb_data++; 342 343 rsvd1_stat1 = *cb_data; 344 cb_data++; 345 346 rsvd1_stat2 = *cb_data; 347 /* cli_out(" RP1 stat1:0x%x\n", rsvd1_stat1); */ 348 /* cli_out(" RP1 stat2:0x%x\n", rsvd1_stat2); */ 349 350 /* 351 * 1. Read the timecode and generate the 52-bit ref-TS using 352 * "((1e9*N + M) mod 2^48) << 4" 353 * 2. Feed this Timecode directly to Input array location 354 */ 355 /*N2 = rsvd1_stat2 & 0xFFFFFF; Lower 24 bits */ 356 u64_H(N1) = rsvd1_stat1 >> 24; 357 u64_L(N1) = rsvd1_stat2 >> 24 | (rsvd1_stat1<<8); 358 359 if (bcn_update) { 360 361 soc_iproc_setreg(unit, 0x0326e03c/*soc_reg_addr(unit, BRCM_RESERVED_IPROC_19, REG_PORT_ANY, 0)*/, u64_H(N1)); 362 soc_iproc_setreg(unit, 0x0326e038/*soc_reg_addr(unit, BRCM_RESERVED_IPROC_18, REG_PORT_ANY, 0)*/, u64_L(N1)); 363 soc_iproc_setreg(unit, 0x0326e034/*soc_reg_addr(unit, BRCM_RESERVED_IPROC_17, REG_PORT_ANY, 0)*/, 0); 364 soc_iproc_setreg(unit, 0x0326e030/*soc_reg_addr(unit, BRCM_RESERVED_IPROC_16, REG_PORT_ANY, 0)*/, 0); 365 366 bcn_update = 0; 367 cli_out("### BCN counter updated with first message\n"); 368 } 369 370 if (ts_update) { 371 uint64 mask_bit; 372 373 /* cli_out("TS Before: "); print_ts(unit); */ 374 375 /* ts52b = (N1 & 0x1FFFFFF)*10000000; //+ 0.59604648328 * N2; */ 376 u64_H(mask_bit) = 0; 377 u64_L(mask_bit) = 0x1FFFFFF; 378 COMPILER_64_AND(N1, mask_bit); 379 COMPILER_64_UMUL_32(N1, 10000000); 380 381 /* ts52b = ts52b & 0xFFFFFFFFFFFF; */ 382 u64_H(mask_bit) = 0xFFFF; 383 u64_L(mask_bit) = 0xFFFFFFFF; 384 COMPILER_64_AND(N1, mask_bit); 385 386 /* ts52b = ts52b << 4; */ 387 COMPILER_64_SHL(N1, 4); 388 389 /* Copy the timestamper for phase_counter update */ 390 COMPILER_64_COPY(ts52b, N1); 391 392 /* Update the timestamper */ 393 394 _bcm_esw_set_timestamp(unit, 1, ts52b); 395 396 ts_update = 0; 397 cli_out("### TS counter updated with first message TS: u:0x%x l:0x%x\n", u64_H(ts52b), u64_L(ts52b)); 398 } 399 400 /* Un-register the callback */ 401 rv = bcm_gdpll_cb_unregister(unit, BCM_GDPLL_CB_RSVD1); 402 if (BCM_FAILURE(rv)) { 403 return CMD_FAIL; 404 } 405 } 406 407 /* cli_out("TS: "); print_ts(unit); */ 408 return rv; 409 } 410 411 #define GDPLL_DEBUG 412 #ifdef GDPLL_DEBUG 413 void dump_chan_param(bcm_gdpll_chan_t *pGdpllChan) 414 { 415 int count; 416 cli_out("******* Reference Event Conf *******\n"); 417 cli_out("event_ref.input_event : %d\n", pGdpllChan->event_ref.input_event); 418 cli_out("event_ref.port : %d\n", pGdpllChan->event_ref.port); 419 cli_out("event_ref.port_event_type : %d\n", pGdpllChan->event_ref.port_event_type); 420 cli_out("event_ref.event_divisor : %d\n", pGdpllChan->event_ref.event_divisor); 421 cli_out("event_ref.event_dest : %d\n", pGdpllChan->event_ref.event_dest); 422 cli_out("event_ref.ts_counter : %d\n", pGdpllChan->event_ref.ts_counter); 423 cli_out("event_ref.ppm_check_enable: %d\n", pGdpllChan->event_ref.ppm_check_enable); 424 425 cli_out("\n******* Feedback Event Conf *******\n"); 426 cli_out("event_fb.input_event : %d\n", pGdpllChan->event_fb.input_event); 427 cli_out("event_fb.port : %d\n", pGdpllChan->event_fb.port); 428 cli_out("event_fb.port_event_type : %d\n", pGdpllChan->event_fb.port_event_type); 429 cli_out("event_fb.event_divisor : %d\n", pGdpllChan->event_fb.event_divisor); 430 cli_out("event_fb.event_dest : %d\n", pGdpllChan->event_fb.event_dest); 431 cli_out("event_fb.ts_counter : %d\n", pGdpllChan->event_fb.ts_counter); 432 cli_out("event_fb.ppm_check_enable: %d\n", pGdpllChan->event_fb.ppm_check_enable); 433 434 cli_out("\nchan_prio : %d\n", pGdpllChan->chan_prio); 435 cli_out("out_event : %d\n", pGdpllChan->out_event); 436 cli_out("out_port : %d\n", pGdpllChan->port); 437 cli_out("ts_pair_dest : %d\n", pGdpllChan->ts_pair_dest); 438 439 cli_out("\n******* Channel config params *******\n"); 440 cli_out("dpll_num_states : %d\n", pGdpllChan->chan_dpll_config.dpll_num_states); 441 cli_out("k1 :"); 442 for (count = 0; count < pGdpllChan->chan_dpll_config.dpll_num_states; count ++) { 443 cli_out(" %d", pGdpllChan->chan_dpll_config.k1[count]); 444 } 445 446 cli_out("\nk1Shift :"); 447 for (count = 0; count < pGdpllChan->chan_dpll_config.dpll_num_states; count ++) { 448 cli_out(" %d", pGdpllChan->chan_dpll_config.k1Shift[count]); 449 } 450 451 cli_out("\nk1k2 :"); 452 for (count = 0; count < pGdpllChan->chan_dpll_config.dpll_num_states; count ++) { 453 cli_out(" %d", pGdpllChan->chan_dpll_config.k1k2[count]); 454 } 455 456 cli_out("\nk1k2Shift :"); 457 for (count = 0; count < pGdpllChan->chan_dpll_config.dpll_num_states; count ++) { 458 cli_out(" %d", pGdpllChan->chan_dpll_config.k1k2Shift[count]); 459 } 460 461 cli_out("\nlockDetThres :"); 462 for (count = 0; count < pGdpllChan->chan_dpll_config.dpll_num_states; count ++) { 463 cli_out(" %d", pGdpllChan->chan_dpll_config.lockDetThres[count]); 464 } 465 466 cli_out("\ndwell_count :"); 467 for (count = 0; count < pGdpllChan->chan_dpll_config.dpll_num_states; count ++) { 468 cli_out(" %d", pGdpllChan->chan_dpll_config.dwell_count[count]); 469 } 470 471 cli_out("\nphase_error_limiter_thres :"); 472 for (count = 0; count < pGdpllChan->chan_dpll_config.dpll_num_states; count ++) { 473 cli_out(" u:0x%x l:0x%x\n", u64_H(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[count]), 474 u64_L(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[count])); 475 } 476 477 cli_out("nco_bits : %d\n",pGdpllChan->chan_dpll_config.nco_bits); 478 cli_out("phase_counter_ref : %d\n",pGdpllChan->chan_dpll_config.phase_counter_ref); 479 cli_out("dpll_num_states : %d\n",pGdpllChan->chan_dpll_config.dpll_num_states); 480 cli_out("idump_mod[0] : %d\n",pGdpllChan->chan_dpll_config.idump_mod[0]); 481 cli_out("phase_error_shift : %d\n",pGdpllChan->chan_dpll_config.phase_error_shift); 482 cli_out("nominal_loop_filter_H: %d\n", u64_H(pGdpllChan->chan_dpll_config.nominal_loop_filter)); 483 cli_out("nominal_loop_filter_L: %d\n", u64_L(pGdpllChan->chan_dpll_config.nominal_loop_filter)); 484 cli_out("invert_phase_error : %d\n",pGdpllChan->chan_dpll_config.invert_phase_error); 485 486 cli_out("norm_phase_error : %d\n",pGdpllChan->chan_dpll_config.norm_phase_error); 487 cli_out("norm_phase_error_thres0 : %d\n",pGdpllChan->chan_dpll_config.norm_phase_error_thres0); 488 cli_out("norm_phase_error_thres1 : %d\n",pGdpllChan->chan_dpll_config.norm_phase_error_thres1); 489 490 cli_out("\n******* Channel state params *******\n"); 491 cli_out("dpll_state : %d\n", pGdpllChan->chan_dpll_state.dpll_state); 492 cli_out("loop_filter : u:0x%x l:0x%x\n", u64_H(pGdpllChan->chan_dpll_state.loop_filter), 493 u64_L(pGdpllChan->chan_dpll_state.loop_filter)); 494 cli_out("dwell_counter : %d\n", pGdpllChan->chan_dpll_state.dwell_counter); 495 cli_out("lockDetFilter : %d\n", pGdpllChan->chan_dpll_state.lockDetFilter); 496 cli_out("offset_H : %d\n", u64_H(pGdpllChan->chan_dpll_state.offset)); 497 cli_out("offset_L : %d\n", u64_L(pGdpllChan->chan_dpll_state.offset)); 498 cli_out("init_flag : %d\n", pGdpllChan->chan_dpll_state.init_flag); 499 cli_out("init_offset_flag : %d\n", pGdpllChan->chan_dpll_state.init_offset_flag); 500 cli_out("phase_counter : u:0x%x l:0x%x\n", 501 u64_H(pGdpllChan->chan_dpll_state.phase_counter), u64_L(pGdpllChan->chan_dpll_state.phase_counter)); 502 cli_out("phaseCounterDelta_H : %d\n", u64_H(pGdpllChan->chan_dpll_state.phaseCounterDelta)); 503 cli_out("phaseCounterDelta_L : %d\n", u64_L(pGdpllChan->chan_dpll_state.phaseCounterDelta)); 504 cli_out("phaseCounterN : %d\n", pGdpllChan->chan_dpll_state.phaseCounterN); 505 cli_out("phaseCounterM : %d\n", pGdpllChan->chan_dpll_state.phaseCounterM); 506 cli_out("phaseCounterFrac : %d\n", pGdpllChan->chan_dpll_state.phaseCounterFrac); 507 cli_out("idumpCounter : %d\n", pGdpllChan->chan_dpll_state.idumpCounter); 508 cli_out("accumPhaseError_H : %d\n", u64_H(pGdpllChan->chan_dpll_state.accumPhaseError)); 509 cli_out("accumPhaseError_L : %d\n", u64_L(pGdpllChan->chan_dpll_state.accumPhaseError)); 510 cli_out("\n***********************************************\n"); 511 } 512 #endif 513 514 uint32 gdpll_config(bcm_gdpll_chan_t *pGdpllChan, char *pStr, char *pNumStr) 515 { 516 uint32 num; 517 518 if (!isint(pNumStr)) { 519 cli_out("### gdpll_config: Error: config number for str:%s\n", pStr); 520 return -1; 521 } 522 num = parse_integer(pNumStr); 523 524 /* Reference */ 525 if (strcmp(pStr, "event_ref_input_event") == 0) 526 pGdpllChan->event_ref.input_event = num; 527 else if (strcmp(pStr, "event_ref_port") == 0) 528 pGdpllChan->event_ref.port = num; 529 else if (strcmp(pStr, "event_ref_port_event_type") == 0) 530 pGdpllChan->event_ref.port_event_type = num; 531 else if (strcmp(pStr, "event_ref_event_divisor") == 0) 532 pGdpllChan->event_ref.event_divisor = num; 533 else if (strcmp(pStr, "event_ref_event_dest") == 0) 534 pGdpllChan->event_ref.event_dest = num; 535 else if (strcmp(pStr, "event_ref_ts_counter") == 0) 536 pGdpllChan->event_ref.ts_counter = num; 537 else if (strcmp(pStr, "event_ref_ppm_check_enable") == 0) 538 pGdpllChan->event_ref.ppm_check_enable = num; 539 540 /* Feedback */ 541 else if (strcmp(pStr, "event_fb_input_event") == 0) 542 pGdpllChan->event_fb.input_event = num; 543 else if (strcmp(pStr, "event_fb_port") == 0) 544 pGdpllChan->event_fb.port = num; 545 else if (strcmp(pStr, "event_fb_port_event_type") == 0) 546 pGdpllChan->event_fb.port_event_type = num; 547 else if (strcmp(pStr, "event_fb_event_divisor") == 0) 548 pGdpllChan->event_fb.event_divisor = num; 549 else if (strcmp(pStr, "event_fb_event_dest") == 0) 550 pGdpllChan->event_fb.event_dest = num; 551 else if (strcmp(pStr, "event_fb_ts_counter") == 0) 552 pGdpllChan->event_fb.ts_counter = num; 553 else if (strcmp(pStr, "event_fb_ppm_check_enable") == 0) 554 pGdpllChan->event_fb.ppm_check_enable = num; 555 556 /* Channel specifics */ 557 else if (strcmp(pStr, "chan_prio") == 0) 558 pGdpllChan->chan_prio = num; 559 else if (strcmp(pStr, "out_event") == 0) 560 pGdpllChan->out_event = num; 561 else if (strcmp(pStr, "out_port") == 0) 562 pGdpllChan->port = num; 563 else if (strcmp(pStr, "ts_pair_dest") == 0) 564 pGdpllChan->ts_pair_dest = num; 565 566 /* DPLL config */ 567 else if (strcmp(pStr, "dpll_config_k1[0]") == 0) 568 pGdpllChan->chan_dpll_config.k1[0] = num; 569 else if (strcmp(pStr, "dpll_config_k1[1]") == 0) 570 pGdpllChan->chan_dpll_config.k1[1] = num; 571 else if (strcmp(pStr, "dpll_config_k1[2]") == 0) 572 pGdpllChan->chan_dpll_config.k1[2] = num; 573 574 else if (strcmp(pStr, "dpll_config_k1Shift[0]") == 0) 575 pGdpllChan->chan_dpll_config.k1Shift[0] = num; 576 else if (strcmp(pStr, "dpll_config_k1Shift[1]") == 0) 577 pGdpllChan->chan_dpll_config.k1Shift[1] = num; 578 else if (strcmp(pStr, "dpll_config_k1Shift[2]") == 0) 579 pGdpllChan->chan_dpll_config.k1Shift[2] = num; 580 581 else if (strcmp(pStr, "dpll_config_k1k2[0]") == 0) 582 pGdpllChan->chan_dpll_config.k1k2[0] = num; 583 else if (strcmp(pStr, "dpll_config_k1k2[1]") == 0) 584 pGdpllChan->chan_dpll_config.k1k2[1] = num; 585 else if (strcmp(pStr, "dpll_config_k1k2[2]") == 0) 586 pGdpllChan->chan_dpll_config.k1k2[2] = num; 587 588 else if (strcmp(pStr, "dpll_config_k1k2Shift[0]") == 0) 589 pGdpllChan->chan_dpll_config.k1k2Shift[0] = num; 590 else if (strcmp(pStr, "dpll_config_k1k2Shift[1]") == 0) 591 pGdpllChan->chan_dpll_config.k1k2Shift[1] = num; 592 else if (strcmp(pStr, "dpll_config_k1k2Shift[2]") == 0) 593 pGdpllChan->chan_dpll_config.k1k2Shift[2] = num; 594 595 else if (strcmp(pStr, "dpll_config_lockDetThres[0]") == 0) 596 pGdpllChan->chan_dpll_config.lockDetThres[0] = num; 597 else if (strcmp(pStr, "dpll_config_lockDetThres[1]") == 0) 598 pGdpllChan->chan_dpll_config.lockDetThres[1] = num; 599 else if (strcmp(pStr, "dpll_config_lockDetThres[2]") == 0) 600 pGdpllChan->chan_dpll_config.lockDetThres[2] = num; 601 602 else if (strcmp(pStr, "dpll_config_lockIndicatorThresholdLo") == 0) 603 pGdpllChan->chan_dpll_config.lockIndicatorThresholdLo = num; 604 else if (strcmp(pStr, "dpll_config_lockIndicatorThresholdHi") == 0) 605 pGdpllChan->chan_dpll_config.lockIndicatorThresholdLHi = num; 606 607 else if (strcmp(pStr, "dpll_config_dwell_count[0]") == 0) 608 pGdpllChan->chan_dpll_config.dwell_count[0] = num; 609 else if (strcmp(pStr, "dpll_config_dwell_count[1]") == 0) 610 pGdpllChan->chan_dpll_config.dwell_count[1] = num; 611 else if (strcmp(pStr, "dpll_config_dwell_count[2]") == 0) 612 pGdpllChan->chan_dpll_config.dwell_count[2] = num; 613 614 else if (strcmp(pStr, "dpll_config_phase_error_limiter_thres_H[0]") == 0) 615 u64_H(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[0]) = num; 616 else if (strcmp(pStr, "dpll_config_phase_error_limiter_thres_L[0]") == 0) 617 u64_L(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[0]) = num; 618 else if (strcmp(pStr, "dpll_config_phase_error_limiter_thres_H[1]") == 0) 619 u64_H(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[1]) = num; 620 else if (strcmp(pStr, "dpll_config_phase_error_limiter_thres_L[1]") == 0) 621 u64_L(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[1]) = num; 622 else if (strcmp(pStr, "dpll_config_phase_error_limiter_thres_H[2]") == 0) 623 u64_H(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[2]) = num; 624 else if (strcmp(pStr, "dpll_config_phase_error_limiter_thres_L[2]") == 0) 625 u64_L(pGdpllChan->chan_dpll_config.phase_error_limiter_thres[2]) = num; 626 627 else if (strcmp(pStr, "dpll_config_nco_bits") == 0) 628 pGdpllChan->chan_dpll_config.nco_bits = num; 629 else if (strcmp(pStr, "dpll_config_phase_counter_ref") == 0) 630 pGdpllChan->chan_dpll_config.phase_counter_ref = num; 631 else if (strcmp(pStr, "dpll_config_dpll_num_states") == 0) 632 pGdpllChan->chan_dpll_config.dpll_num_states = num; 633 634 else if (strcmp(pStr, "dpll_config_idump_mod[0]") == 0) 635 pGdpllChan->chan_dpll_config.idump_mod[0] = num; 636 else if (strcmp(pStr, "dpll_config_idump_mod[1]") == 0) 637 pGdpllChan->chan_dpll_config.idump_mod[1] = num; 638 else if (strcmp(pStr, "dpll_config_idump_mod[2]") == 0) 639 pGdpllChan->chan_dpll_config.idump_mod[2] = num; 640 641 else if (strcmp(pStr, "dpll_config_phase_error_shift") == 0) 642 pGdpllChan->chan_dpll_config.phase_error_shift = num; 643 else if (strcmp(pStr, "dpll_config_nominal_loop_filter_H") == 0) 644 u64_H(pGdpllChan->chan_dpll_config.nominal_loop_filter) = num; 645 else if (strcmp(pStr, "dpll_config_nominal_loop_filter_L") == 0) 646 u64_L(pGdpllChan->chan_dpll_config.nominal_loop_filter) = num; 647 else if (strcmp(pStr, "dpll_config_invert_phase_error") == 0) 648 pGdpllChan->chan_dpll_config.invert_phase_error = num; 649 else if (strcmp(pStr, "dpll_config_norm_phase_error") == 0) 650 pGdpllChan->chan_dpll_config.norm_phase_error = num; 651 else if (strcmp(pStr, "dpll_config_norm_phase_thres0") == 0) 652 pGdpllChan->chan_dpll_config.norm_phase_error_thres0 = num; 653 else if (strcmp(pStr, "dpll_config_norm_phase_thres1") == 0) 654 pGdpllChan->chan_dpll_config.norm_phase_error_thres1 = num; 655 656 /* DPLL State */ 657 else if (strcmp(pStr, "dpll_state_dpll_state") == 0) 658 pGdpllChan->chan_dpll_state.dpll_state = num; 659 else if (strcmp(pStr, "dpll_state_loop_filter_H") == 0) 660 u64_H(pGdpllChan->chan_dpll_state.loop_filter) = num; 661 else if (strcmp(pStr, "dpll_state_loop_filter_L") == 0) 662 u64_L(pGdpllChan->chan_dpll_state.loop_filter) = num; 663 else if (strcmp(pStr, "dpll_state_dwell_counter") == 0) 664 pGdpllChan->chan_dpll_state.dwell_counter = num; 665 else if (strcmp(pStr, "dpll_state_lockDetFilter") == 0) 666 pGdpllChan->chan_dpll_state.lockDetFilter = num; 667 else if (strcmp(pStr, "dpll_state_offset_H") == 0) 668 u64_H(pGdpllChan->chan_dpll_state.offset) = num; 669 else if (strcmp(pStr, "dpll_state_offset_L") == 0) 670 u64_L(pGdpllChan->chan_dpll_state.offset) = num; 671 else if (strcmp(pStr, "dpll_state_init_flag") == 0) 672 pGdpllChan->chan_dpll_state.init_flag = num; 673 else if (strcmp(pStr, "dpll_state_init_offset_flag") == 0) 674 pGdpllChan->chan_dpll_state.init_offset_flag = num; 675 else if (strcmp(pStr, "dpll_state_phase_counter_H") == 0) 676 u64_H(pGdpllChan->chan_dpll_state.phase_counter) = num; 677 else if (strcmp(pStr, "dpll_state_phase_counter_L") == 0) 678 u64_L(pGdpllChan->chan_dpll_state.phase_counter) = num; 679 else if (strcmp(pStr, "dpll_state_phaseCounterDelta_H") == 0) 680 u64_H(pGdpllChan->chan_dpll_state.phaseCounterDelta) = num; 681 else if (strcmp(pStr, "dpll_state_phaseCounterDelta_L") == 0) 682 u64_L(pGdpllChan->chan_dpll_state.phaseCounterDelta) = num; 683 else if (strcmp(pStr, "dpll_state_phaseCounterN") == 0) 684 pGdpllChan->chan_dpll_state.phaseCounterN = num; 685 else if (strcmp(pStr, "dpll_state_phaseCounterM") == 0) 686 pGdpllChan->chan_dpll_state.phaseCounterM = num; 687 else if (strcmp(pStr, "dpll_state_phaseCounterFrac") == 0) 688 pGdpllChan->chan_dpll_state.phaseCounterFrac = num; 689 else if (strcmp(pStr, "dpll_state_idumpCounter") == 0) 690 pGdpllChan->chan_dpll_state.idumpCounter = num; 691 else if (strcmp(pStr, "dpll_state_accumPhaseError_H") == 0) 692 u64_H(pGdpllChan->chan_dpll_state.accumPhaseError) = num; 693 else if (strcmp(pStr, "dpll_state_accumPhaseError_L") == 0) 694 u64_L(pGdpllChan->chan_dpll_state.accumPhaseError) = num; 695 else if (strcmp(pStr, "use_case_flag") == 0) 696 use_case_flag = num; 697 else if (strcmp(pStr, "disable_debug_log") == 0) 698 disable_debug_log = num; 699 else 700 cli_out("### gdpll_config: ERROR: config str:%s\n", pStr); 701 702 return 0; 703 } 704 705 static int 706 _bcm_future_cpri_enable(int unit, int port, uint64 offset) 707 { 708 int rv = BCM_E_NONE; 709 710 #ifdef CPRIMOD_SUPPORT 711 rv = cprimod_tx_framer_tgen_enable(unit, port, 0/*enable*/); 712 if (BCM_FAILURE(rv)) { 713 cli_out("CPRI TGEN_ENABLE setting 0 failed %s\n", bcm_errmsg(rv)); 714 return CMD_FAIL; 715 } 716 717 rv = cprimod_tx_framer_tgen_offset_set(unit, port, offset); 718 if (BCM_FAILURE(rv)) { 719 cli_out("CPRI TGEN_OFFSET setting failed %s\n", bcm_errmsg(rv)); 720 return CMD_FAIL; 721 } 722 723 rv = cprimod_tx_framer_tgen_enable(unit, port, 1/*enable*/); 724 if (BCM_FAILURE(rv)) { 725 cli_out("CPRI TGEN_ENABLE setting 1 failed %s\n", bcm_errmsg(rv)); 726 return CMD_FAIL; 727 } 728 #endif 729 730 return rv; 731 } 732 733 #define ToD_TYPE_NTP 0x1 734 #define ToD_TYPE_PTP 0x2 735 736 static int 737 _bcm_program_ptpntptod(int unit, bcm_time_spec_t ts, uint32 tod_type) 738 { 739 int rv = BCM_E_NONE; 740 uint32 regval; 741 uint32 regval_sec; 742 uint64 frac_sec; 743 uint64 nanosec, div; 744 uint64 val_64b; 745 746 /* regval_sec = new_time.u48_sec; */ 747 regval_sec = COMPILER_64_LO(ts.seconds); 748 regval_sec = ((regval_sec & 1) << 31) | (regval_sec >> 1); 749 750 if (tod_type & ToD_TYPE_NTP) { 751 752 /* Program the initial NTP-ToD frequency control */ 753 WRITE_NTP_TIME_FREQ_CONTROLr(unit, 0x44B82FA1); 754 755 /* NTP timestamps are 64 bit, Q32 seconds, i.e seconds * 2^32, so bit 0 == 1/2^32 of a second */ 756 /* Convert from nanoseconds to those fractions of a second */ 757 /* frac_sec = (((uint64_t)new_time.u32_Nsec) << 32) / ONE_BILLION; */ 758 COMPILER_64_SET(div, 0, 1000000000); /* ONE_BILLION */ 759 COMPILER_64_SET(nanosec, 0, ts.nanoseconds); 760 COMPILER_64_SHL(nanosec, 32); 761 COMPILER_64_UDIV_64(nanosec, div); 762 COMPILER_64_COPY(frac_sec, nanosec); 763 764 /* NTP time is stored in seconds and fractional seconds */ 765 WRITE_NTP_TIME_SECr(unit, regval_sec); 766 767 COMPILER_64_COPY(val_64b, frac_sec); 768 COMPILER_64_SHR(val_64b, 6); 769 WRITE_NTP_TIME_FRAC_SEC_UPPERr(unit, COMPILER_64_LO(val_64b)); 770 771 COMPILER_64_COPY(val_64b, frac_sec); 772 COMPILER_64_SHL(val_64b, 26); 773 WRITE_NTP_TIME_FRAC_SEC_LOWERr(unit, COMPILER_64_LO(val_64b)); 774 775 READ_NTP_TIME_CONTROLr(unit, ®val); 776 regval |= 0x1f; /* Set load-enable bits, |B04...B00|. */ 777 778 WRITE_NTP_TIME_CONTROLr(unit, regval); 779 780 regval &= ~(0x1f); /* Clear load-enable bits, |B04...B00|. */ 781 regval |= 0x20; /* Set count-enable bit, |B05|. */ 782 WRITE_NTP_TIME_CONTROLr(unit, regval); 783 /* cli_out("### TS After NTP write: "); print_ts(unit); */ 784 } 785 786 if (tod_type & ToD_TYPE_PTP) { 787 788 /* Program the initial PTP-ToD frequency control */ 789 WRITE_IEEE1588_TIME_FREQ_CONTROLr(unit, 0x10000000); 790 791 /* 1588 time is stored in seconds and nanoseconds */ 792 WRITE_IEEE1588_TIME_SECr(unit, regval_sec); 793 WRITE_IEEE1588_TIME_FRAC_SEC_UPPERr(unit, ts.nanoseconds >> 6); 794 WRITE_IEEE1588_TIME_FRAC_SEC_LOWERr(unit, ts.nanoseconds << 26); 795 796 READ_IEEE1588_TIME_CONTROLr(unit, ®val); 797 regval |= 0x1f; /* Set load-enable bits, |B04...B00|. */ 798 WRITE_IEEE1588_TIME_CONTROLr(unit, regval); 799 regval &= ~(0x1f); /* Clear load-enable bits, |B04...B00|. */ 800 regval |= 0x20; /* Set count-enable bit, |B05|. */ 801 WRITE_IEEE1588_TIME_CONTROLr(unit, regval); 802 /* cli_out("### TS After PTP write: "); print_ts(unit); */ 803 } 804 805 return rv; 806 } 807 808 /* Enable this macro rx.c DO-NOT have the timestamp conversion logic implemented */ 809 /* #define RX_TS_CONVERTION */ 810 811 STATIC bcm_rx_t 812 roe_pkt_cb_handler(int unit, bcm_pkt_t *info, void *cookie) 813 { 814 uint64 T2 = 0; /* RX packet timestamp */ 815 uint64 C = 0; /* For CPRI-TX gate opening */ 816 uint32 delta = 3000 * 16; /* 3uSec jitter buffer, ns */ 817 uint32 future_offset = 10 * 1000000 * 16; /* 20mSec, ns */ 818 819 #ifdef RX_TS_CONVERTION 820 uint64 T1 = 0; /* Current timestamper value */ 821 int timestamper = 1; 822 uint32 val32; 823 824 u64_L(T2) = info->rx_timestamp; 825 826 _bcm_esw_get_timestamp(unit, timestamper, &T1); 827 828 if (COMPILER_64_BITTEST(T1, 35) == COMPILER_64_BITTEST(T2, 31)) { 829 /* If T1[35] == T2[31], then set T2[47..32] = T1[51..36], T2 = T2 << 4 */ 830 val32 = u64_H(T1); 831 val32 = val32 >> 4; 832 val32 &= 0xFFFF; 833 834 u64_H(T2) &= ~0xFFFF; 835 u64_H(T2) |= val32; 836 COMPILER_64_SHL(T2, 4); 837 } else if ((COMPILER_64_BITTEST(T1, 35) == 1) && (COMPILER_64_BITTEST(T2, 31) == 0)) { 838 /* If T1[35] == 1 and T2[31] == 0, then set T2[47..32] = T1[51..36], T2 = T2 << 4 */ 839 val32 = u64_H(T1); 840 val32 = val32 >> 4; 841 val32 &= 0xFFFF; 842 843 u64_H(T2) &= ~0xFFFF; 844 u64_H(T2) |= val32; 845 COMPILER_64_SHL(T2, 4); 846 } else if ((COMPILER_64_BITTEST(T1, 35) == 0) && (COMPILER_64_BITTEST(T2, 31) == 1)) { 847 /* If T1[35] == 0 and T2[31] == 1, then set T2[47..32] = T1[51..36] - 1, T2= T2 << 4 */ 848 val32 = u64_H(T1); 849 val32 = val32 >> 4; 850 val32 -= 1; 851 val32 &= 0xFFFF; 852 853 u64_H(T2) &= ~0xFFFF; 854 u64_H(T2) |= val32; 855 COMPILER_64_SHL(T2, 4); 856 } 857 #else 858 u64_L(T2) = info->rx_timestamp; 859 u64_H(T2) = info->rx_timestamp_upper; 860 #endif 861 862 /* C = T2 + 160,000,000 + Delta */ 863 COMPILER_64_ADD_32(C, T2); 864 COMPILER_64_ADD_32(C, future_offset); 865 COMPILER_64_ADD_32(C, delta); 866 867 _bcm_future_cpri_enable(unit, port_out, C); 868 869 #ifdef RX_TS_CONVERTION 870 cli_out(" ### \n T1(H/L):0x%x/0x%x \n T2(32b):0x%x \n T2_computed(H/L): 0x%x/0x%x \n future_time(H/L): 0x%x/0x%x\n\n", 871 u64_H(T1), u64_L(T1), info->rx_timestamp, u64_H(T2), u64_L(T2), u64_H(C), u64_L(C)); 872 #else 873 cli_out(" ### \n T2(pkt-ts):0x%x/0x%x \n future_time(H/L): 0x%x/0x%x\n\n", 874 info->rx_timestamp_upper, info->rx_timestamp, u64_H(C), u64_L(C)); 875 #endif 876 877 /* Un-register the cb handler */ 878 bcm_rx_unregister(unit, roe_pkt_cb_handler, 101); 879 return BCM_RX_HANDLED; 880 } 881 882 cmd_result_t cmd_gdpll(int unit, args_t *args) 883 { 884 char *arg_string_p = NULL; 885 int result; 886 char *c, *filename; 887 int chan; 888 int enable; 889 char line[300]; 890 int i; 891 bcm_gdpll_chan_t gdpll_chan; 892 uint32 poll_period_uSec = 30*60*1000000; /* Poll for 30mins */ 893 uint32 rval; 894 uint32 poll_interval_uSec = 0; 895 uint32 pps_detect = 0; 896 soc_field_t field = 0; 897 uint32 alloc_sz = 0; 898 sal_thread_t thread_id; 899 900 901 uint32 flags = BCM_GDPLL_CONF_DPLL | 902 BCM_GDPLL_EVENT_CONFIG_REF | BCM_GDPLL_EVENT_CONFIG_FB | 903 BCM_GDPLL_CHAN_ALLOC | BCM_GDPLL_CHAN_SET_PRIORITY | 904 BCM_GDPLL_CHAN_OUTPUT_CONF; 905 sal_memset(&gdpll_chan, 0, sizeof(bcm_gdpll_chan_t)); 906 907 arg_string_p = ARG_GET(args); 908 909 if (arg_string_p == NULL) { 910 return CMD_USAGE; 911 } 912 913 if (!sh_check_attached(ARG_CMD(args), unit)) { 914 return CMD_FAIL; 915 } 916 917 if (pGdpllAppContext == NULL) { 918 alloc_sz = sizeof(gdpll_app_context_t); 919 pGdpllAppContext = sal_alloc(alloc_sz, "GDPLL module"); 920 if (NULL != pGdpllAppContext) { 921 sal_memset(pGdpllAppContext, 0, alloc_sz); 922 thread_id = sal_thread_create("GDPLL Monitor", SAL_THREAD_STKSZ, 100, 923 gdpll_channel_monitor_thread, INT_TO_PTR(unit)); 924 925 if (thread_id == SAL_THREAD_ERROR) { 926 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "GDPLL DIAG: Channel monitor thread create failed\n"))); 927 sal_free(pGdpllAppContext); 928 pGdpllAppContext = NULL; 929 } 930 } 931 } 932 933 if (parse_cmp("Flush", arg_string_p, 0)) { 934 result = bcm_gdpll_flush(unit); 935 if (BCM_FAILURE(result)) { 936 cli_out("Command failed. %s\n", bcm_errmsg(result)); 937 return CMD_FAIL; 938 } 939 } else if (parse_cmp("Rsvd1cbreg", arg_string_p, 0)) { 940 rsvd1count = 2; 941 result = bcm_gdpll_cb_register(unit, BCM_GDPLL_CB_RSVD1, bcm_gdpll_cb_rsvd1, NULL); 942 if (BCM_FAILURE(result)) { 943 return CMD_FAIL; 944 } 945 } else if (parse_cmp("Rsvd1cbunreg", arg_string_p, 0)) { 946 result = bcm_gdpll_cb_unregister(unit, BCM_GDPLL_CB_RSVD1); 947 if (BCM_FAILURE(result)) { 948 return CMD_FAIL; 949 } 950 } else if (parse_cmp("Debug", arg_string_p, 0)) { 951 c = ARG_GET(args); 952 if (!isint(c)) { 953 cli_out("%s: Error: Channel number \n", ARG_CMD(args)); 954 return(CMD_USAGE); 955 } 956 enable = parse_integer(c); 957 958 if (!enable) { 959 /* Disable GDPLL debug feature so that there wont be the callback */ 960 result = bcm_gdpll_debug (unit, 0); 961 if (BCM_FAILURE(result)) { 962 cli_out("Command failed. %s\n", bcm_errmsg(result)); 963 return CMD_FAIL; 964 } 965 966 /* Introduce delay for the pending wrights */ 967 sal_usleep(100 * 1000); 968 969 /* Close the file pointer */ 970 if (fp) { 971 #ifndef NO_FILEIO 972 sal_fclose((FILE *)fp); 973 cli_out("### gdpll debug file close\n"); 974 #endif 975 fp = NULL; 976 } 977 978 debug_enable_flag = 0; 979 return CMD_OK; 980 } 981 982 if (enable && debug_enable_flag) { 983 /* If already enabled, user needs to disable before re-enabling */ 984 cli_out("Already enabled.. \n"); 985 return CMD_FAIL; 986 } 987 988 /* Read the user file name */ 989 if (enable) { 990 c = ARG_GET(args); 991 filename = c; 992 if (filename == NULL) { 993 cli_out("%s: Error: No file specified\n", ARG_CMD(args)); 994 return(CMD_USAGE); 995 } 996 997 if (strcmp(filename, "UDP") == 0) { 998 cli_out("Sending out as UDP packet\n"); 999 1000 int ttl = L3_header[10]; 1001 bcm_ip_t src_ip = soc_ntohl_load(&L3_header[14]); 1002 bcm_ip_t dest_ip = soc_ntohl_load(&L3_header[18]); 1003 int udp_src_port = soc_ntohs_load(&L3_header[22]); 1004 int udp_dst_port = soc_ntohs_load(&L3_header[24]); 1005 1006 parse_table_t pt; 1007 parse_table_init(unit, &pt); 1008 parse_table_add(&pt, "DestMAC", PQ_DFL | PQ_MAC, NULL, dest_mac, NULL); 1009 parse_table_add(&pt, "DestAddr", PQ_DFL | PQ_IP, NULL, &dest_ip, NULL); 1010 parse_table_add(&pt, "SrcMAC", PQ_DFL | PQ_MAC, NULL, src_mac, NULL); 1011 parse_table_add(&pt, "SrcAddr", PQ_DFL | PQ_IP, NULL, &src_ip, NULL); 1012 parse_table_add(&pt, "UDPSrcPort", PQ_DFL | PQ_INT, NULL, &udp_src_port, NULL); 1013 parse_table_add(&pt, "UDPDestPort", PQ_DFL | PQ_INT, NULL, &udp_dst_port, NULL); 1014 parse_table_add(&pt, "Vlan", PQ_DFL | PQ_INT, NULL, &vlan, NULL); 1015 parse_table_add(&pt, "TTL", PQ_DFL | PQ_INT, NULL, &ttl, NULL); 1016 if (parse_arg_eq(args, &pt) < 0) { 1017 cli_out("%s: Error: Unknown option: %s\n", ARG_CMD(args), ARG_CUR(args)); 1018 parse_arg_eq_done(&pt); 1019 return(CMD_FAIL); 1020 } 1021 parse_arg_eq_done(&pt); 1022 1023 L3_header[10] = ttl & 0xff; 1024 soc_htonl_store(&L3_header[14], src_ip); 1025 soc_htonl_store(&L3_header[18], dest_ip); 1026 soc_htons_store(&L3_header[22], udp_src_port); 1027 soc_htons_store(&L3_header[24], udp_dst_port); 1028 1029 /* Register the callback function */ 1030 result = bcm_gdpll_debug_cb_register (unit, NULL, gdpll_debug_udp_cb); 1031 if (BCM_FAILURE(result)) { 1032 cli_out("Command failed. %s\n", bcm_errmsg(result)); 1033 return CMD_FAIL; 1034 } 1035 } 1036 #ifndef NO_FILEIO 1037 else { 1038 /* Open the file */ 1039 fp = sal_fopen(filename, "w+"); 1040 if (!fp) { 1041 cli_out("%s: Error: Unable to open file: %s\n", 1042 ARG_CMD(args), filename); 1043 return CMD_FAIL; 1044 } 1045 /* Register the callback function */ 1046 result = bcm_gdpll_debug_cb_register (unit, NULL, gdpll_debug_cb); 1047 if (BCM_FAILURE(result)) { 1048 cli_out("Command failed. %s\n", bcm_errmsg(result)); 1049 return CMD_FAIL; 1050 } 1051 } 1052 #endif 1053 } 1054 1055 /* Set enable for GDPLL debug feature */ 1056 result = bcm_gdpll_debug (unit, enable); 1057 if (BCM_FAILURE(result)) { 1058 cli_out("Command failed. %s\n", bcm_errmsg(result)); 1059 return CMD_FAIL; 1060 } 1061 1062 debug_enable_flag = enable ? 1:0; 1063 1064 } else if (parse_cmp("Offset", arg_string_p, 0)) { 1065 arg_string_p = ARG_GET(args); 1066 if (arg_string_p == NULL) { 1067 return CMD_USAGE; 1068 } 1069 1070 if (parse_cmp("Set", arg_string_p, 0)) { 1071 uint64 Offset; 1072 c = ARG_GET(args); 1073 if (!isint(c)) { 1074 cli_out("%s: Error: Channel number \n", ARG_CMD(args)); 1075 return(CMD_USAGE); 1076 } 1077 chan = parse_integer(c); 1078 1079 c = ARG_GET(args); 1080 if (!isint(c)) { 1081 cli_out("%s: Error: Offset_H \n", ARG_CMD(args)); 1082 return(CMD_USAGE); 1083 } 1084 u64_H(Offset) = parse_integer(c); 1085 1086 c = ARG_GET(args); 1087 if (!isint(c)) { 1088 cli_out("%s: Error: Offset_L \n", ARG_CMD(args)); 1089 return(CMD_USAGE); 1090 } 1091 u64_L(Offset) = parse_integer(c); 1092 1093 _bcm_esw_gdpll_offset_set(unit, chan, Offset); 1094 1095 } else if (parse_cmp("Get", arg_string_p, 0)) { 1096 uint64 Offset; 1097 c = ARG_GET(args); 1098 if (!isint(c)) { 1099 cli_out("%s: Error: Channel number \n", ARG_CMD(args)); 1100 return(CMD_USAGE); 1101 } 1102 chan = parse_integer(c); 1103 1104 _bcm_esw_gdpll_offset_get(unit, chan, &Offset); 1105 cli_out("### GDPLL DIAG: chan:%d offset(H/L):0x%x/0x%x\n", chan, u64_H(Offset), u64_L(Offset)); 1106 1107 } else { 1108 cli_out("Error: Invalid Option for Offset\n"); 1109 return(CMD_USAGE); 1110 } 1111 } else if (parse_cmp("Chan", arg_string_p, 0)) { 1112 arg_string_p = ARG_GET(args); 1113 if (arg_string_p == NULL) { 1114 return CMD_USAGE; 1115 } 1116 1117 if (parse_cmp("Destroy", arg_string_p, 0)) { 1118 c = ARG_GET(args); 1119 if (!isint(c)) { 1120 cli_out("%s: Error: Channel number \n", ARG_CMD(args)); 1121 return(CMD_USAGE); 1122 } 1123 chan = parse_integer(c); 1124 1125 result = bcm_gdpll_chan_destroy(unit, chan); 1126 if (BCM_FAILURE(result)) { 1127 cli_out("Channel destroy failed with error: %s\n", bcm_errmsg(result)); 1128 return CMD_FAIL; 1129 } 1130 } else if (parse_cmp("Enable", arg_string_p, 0)) { 1131 c = ARG_GET(args); 1132 if (!isint(c)) { 1133 cli_out("%s: Error: Channel number \n", ARG_CMD(args)); 1134 return(CMD_USAGE); 1135 } 1136 chan = parse_integer(c); 1137 1138 result = bcm_gdpll_chan_enable(unit, chan, 1); 1139 if (BCM_FAILURE(result)) { 1140 cli_out("Command failed. %s\n", bcm_errmsg(result)); 1141 return CMD_FAIL; 1142 } 1143 1144 /*cli_out("After Enable TS: "); print_ts(unit); */ 1145 } else if (parse_cmp("Disable", arg_string_p, 0)) { 1146 c = ARG_GET(args); 1147 if (!isint(c)) { 1148 cli_out("%s: Error: Channel number \n", ARG_CMD(args)); 1149 return(CMD_USAGE); 1150 } 1151 1152 chan = parse_integer(c); 1153 result = bcm_gdpll_chan_enable(unit, chan, 0); 1154 if (BCM_FAILURE(result)) { 1155 cli_out("Command failed. %s\n", bcm_errmsg(result)); 1156 return CMD_FAIL; 1157 } 1158 1159 } else if (parse_cmp("Status", arg_string_p, 0)) { 1160 uint32 status = 0; 1161 c = ARG_GET(args); 1162 if (!isint(c)) { 1163 cli_out("%s: Error: Channel number \n", ARG_CMD(args)); 1164 return(CMD_USAGE); 1165 } 1166 1167 chan = parse_integer(c); 1168 result = bcm_gdpll_chan_state_get(unit, chan, &status); 1169 if (BCM_FAILURE(result)) { 1170 cli_out("Command failed. %s\n", bcm_errmsg(result)); 1171 return CMD_FAIL; 1172 } 1173 cli_out("Status:0x%x\n", status); 1174 1175 } else if (parse_cmp("Debug", arg_string_p, 0)) { 1176 uint32 debug_mode; 1177 1178 /* Read the channel number */ 1179 c = ARG_GET(args); 1180 if (!isint(c)) { 1181 cli_out("%s: Error: Channel number \n", ARG_CMD(args)); 1182 return(CMD_USAGE); 1183 } 1184 chan = parse_integer(c); 1185 1186 /* Read the debug mode */ 1187 c = ARG_GET(args); 1188 if (!isint(c)) { 1189 cli_out("%s: Error: Debug mode \n", ARG_CMD(args)); 1190 return(CMD_USAGE); 1191 } 1192 debug_mode = parse_integer(c); 1193 1194 result = bcm_gdpll_chan_debug_enable(unit, chan, debug_mode, 1); 1195 if (BCM_FAILURE(result)) { 1196 cli_out("Command failed. %s\n", bcm_errmsg(result)); 1197 return CMD_FAIL; 1198 } 1199 1200 } else if (parse_cmp("Monitor", arg_string_p, 0)) { 1201 /* Read the channel number */ 1202 c = ARG_GET(args); 1203 if (!isint(c)) { 1204 cli_out("%s: Error: Channel number \n", ARG_CMD(args)); 1205 return(CMD_USAGE); 1206 } 1207 chan = parse_integer(c); 1208 1209 if (pGdpllAppContext && (chan>=0) && (chan < BCM_GDPLL_NUM_CHANNELS)) { 1210 pGdpllAppContext->chan_mon_flag[chan] = 1; 1211 } 1212 1213 } else if (parse_cmp("Dump", arg_string_p, 0)) { 1214 uint32 pair_avail; 1215 uint32 ia_in_status; 1216 1217 /* Read the channel number */ 1218 c = ARG_GET(args); 1219 if (!isint(c)) { 1220 cli_out("%s: Error: Channel number \n", ARG_CMD(args)); 1221 return(CMD_USAGE); 1222 } 1223 chan = parse_integer(c); 1224 1225 if (chan < 32) { 1226 soc_iproc_getreg(unit, soc_reg_addr(unit, NS_GDPLL_IA_TS_PAIR_AVAILABLE0r, REG_PORT_ANY, 0/*idx*/), &pair_avail); 1227 soc_iproc_getreg(unit, soc_reg_addr(unit, NS_GDPLL_IA_IN_STATUS0r, REG_PORT_ANY, 0/*idx*/), &ia_in_status); 1228 pair_avail = pair_avail & (1 << chan); 1229 ia_in_status = ia_in_status & (1 << chan); 1230 } else if (chan < 64) { 1231 soc_iproc_getreg(unit, soc_reg_addr(unit, NS_GDPLL_IA_TS_PAIR_AVAILABLE1r, REG_PORT_ANY, 0/*idx*/), &pair_avail); 1232 soc_iproc_getreg(unit, soc_reg_addr(unit, NS_GDPLL_IA_IN_STATUS1r, REG_PORT_ANY, 0/*idx*/), &ia_in_status); 1233 pair_avail = pair_avail & (1 << (chan-32)); 1234 ia_in_status = ia_in_status & (1 << (chan-32)); 1235 } else if (chan < 96) { 1236 soc_iproc_getreg(unit, soc_reg_addr(unit, NS_GDPLL_IA_TS_PAIR_AVAILABLE2r, REG_PORT_ANY, 0/*idx*/), &pair_avail); 1237 soc_iproc_getreg(unit, soc_reg_addr(unit, NS_GDPLL_IA_IN_STATUS2r, REG_PORT_ANY, 0/*idx*/), &ia_in_status); 1238 pair_avail = pair_avail & (1 << (chan-64)); 1239 ia_in_status = ia_in_status & (1 << (chan-64)); 1240 } else if (chan < 128) { 1241 soc_iproc_getreg(unit, soc_reg_addr(unit, NS_GDPLL_IA_TS_PAIR_AVAILABLE3r, REG_PORT_ANY, 0/*idx*/), &pair_avail); 1242 soc_iproc_getreg(unit, soc_reg_addr(unit, NS_GDPLL_IA_IN_STATUS3r, REG_PORT_ANY, 0/*idx*/), &ia_in_status); 1243 pair_avail = pair_avail & (1 << (chan-96)); 1244 ia_in_status = ia_in_status & (1 << (chan-96)); 1245 } 1246 1247 /* Dump the debug info */ 1248 if((chan>=0) && (chan < BCM_GDPLL_NUM_CHANNELS)) { 1249 soc_iproc_getreg(unit, soc_reg_addr(unit, NS_GDPLL_M7_ERROR_INFOr, REG_PORT_ANY, 0/*idx*/), &rval); 1250 1251 cli_out("### GDPLL DIAG: Dump for chan:%d\n", chan); 1252 cli_out(" PAIR_AVAIL(%d): %d\n", chan, pair_avail); 1253 cli_out(" IA_IN_STATUS(%d): %d\n", chan, ia_in_status); 1254 cli_out(" M7 Trigger count: 0x%x\n", rval); 1255 } 1256 1257 } else if (parse_cmp("Create", arg_string_p, 0)) { 1258 1259 cli_out("### chan create flags:0x%x\n", flags); 1260 1261 #ifndef NO_FILEIO 1262 FILE * volatile fptr = NULL; 1263 #endif 1264 c = ARG_GET(args); 1265 filename = c; 1266 if (filename == NULL) { 1267 cli_out("%s: Error: No file specified\n", ARG_CMD(args)); 1268 return(CMD_USAGE); 1269 } 1270 1271 #ifndef NO_FILEIO 1272 /* Open the file */ 1273 fptr = sal_fopen(filename, "r"); 1274 if (!fptr) { 1275 cli_out("%s: Error: Unable to open file: %s\n", 1276 ARG_CMD(args), filename); 1277 return CMD_FAIL; 1278 } 1279 #endif 1280 1281 use_case_flag = 0; 1282 disable_debug_log = 0; 1283 1284 /* Read the config from a file line by line */ 1285 while (sal_fgets(line, sizeof(line), fptr)) { 1286 for (i=0; i < sizeof(line); i++) { 1287 if (line[i] == '=') { 1288 line[strlen(line)-1] = '\0'; 1289 line[i] = '\0'; 1290 gdpll_config(&gdpll_chan, line, line+i+1); 1291 break; 1292 } 1293 } 1294 } 1295 1296 if (use_case_flag == 1) 1297 { 1298 uint64 TS; 1299 uint64 mask_bit; 1300 uint64 offset; 1301 #ifdef CPRIMOD_SUPPORT 1302 uint32 cpriPort; 1303 #endif 1304 /* cli_out("######## use_case_1A\n"); */ 1305 cli_out("### GDPLL DIAG: use_case 1A config\n"); 1306 1307 /* If the computation of future time is taken care by caller of this diag, then 1308 * the next arguments will be phase_counter_H and phase_counter_L 1309 * Ex: SV-team test framework needs this. 1310 */ 1311 c = ARG_GET(args); 1312 if ((c != NULL) && isint(c)) { 1313 u64_H(gdpll_chan.chan_dpll_state.phase_counter) = parse_integer(c); 1314 1315 c = ARG_GET(args); 1316 if (!isint(c)) { 1317 cli_out("%s: Error: Improper phase_counter_L\n", ARG_CMD(args)); 1318 return(CMD_USAGE); 1319 } 1320 u64_L(gdpll_chan.chan_dpll_state.phase_counter) = parse_integer(c); 1321 1322 cli_out("### Use-case-1a: phase_counter values from user H/L: %d / %d\n", 1323 u64_H(gdpll_chan.chan_dpll_state.phase_counter), 1324 u64_L(gdpll_chan.chan_dpll_state.phase_counter)); 1325 } else { 1326 1327 poll_period_uSec = 30*60*1000000; /* Poll for 30mins */ 1328 poll_interval_uSec = 0; pps_detect = 0; 1329 u64_H(mask_bit) = 0xFFFF; 1330 u64_L(mask_bit) = 0xFFFFFFFF; 1331 1332 if ((c != NULL) && parse_cmp("SyncBS0HB", c, 0)) { 1333 cli_out(" Note: 1A locking in close to input pulse on BS0HB\n"); 1334 field = BS0_HEARTBEATf; 1335 poll_interval_uSec = 1; /* Poll for every 1uSec */ 1336 1337 } else if ((c != NULL) && parse_cmp("SyncBS1HB", c, 0)) { 1338 cli_out(" Note: 1A locking in close to input pulse on BS1HB\n"); 1339 field = BS1_HEARTBEATf; 1340 poll_interval_uSec = 1; /* Poll for every 1uSec */ 1341 1342 } else if ((c != NULL) && parse_cmp("SyncGPIO2", c, 0)) { 1343 cli_out(" Note: 1A locking in close to input pulse on GPIO2\n"); 1344 field = TS_GPIO_2f; 1345 poll_interval_uSec = 1; /* Poll for every 1uSec */ 1346 1347 } else if (c != NULL) { 1348 cli_out("%s: Error: Improper arg for 1A\n", ARG_CMD(args)); 1349 return(CMD_USAGE); 1350 } 1351 1352 /* If the Sync is expected for (1G+1A) case */ 1353 if (poll_interval_uSec) { 1354 1355 cli_out(" Note: This logic is to test 1A+1G in sync\n"); 1356 cli_out(" Expectation is ensure 1G is locked and try enabling 1A\n"); 1357 cli_out(" close to 1PPS-In pulse of 1G\n"); 1358 1359 /* Clear if any flag is already set */ 1360 SOC_IF_ERROR_RETURN(READ_NS_MISC_EVENT_STATUSr(unit, &rval)); 1361 soc_reg_field_set(unit, NS_MISC_EVENT_STATUSr, &rval, field, 1); 1362 SOC_IF_ERROR_RETURN(WRITE_NS_MISC_EVENT_STATUSr(unit, rval)); 1363 1364 /* Poll on the next 1PPS event */ 1365 while(poll_period_uSec > 0) { 1366 SOC_IF_ERROR_RETURN(READ_NS_MISC_EVENT_STATUSr(unit, &rval)); 1367 if (soc_reg_field_get(unit, NS_MISC_EVENT_STATUSr, rval, field)) { 1368 pps_detect = 1; 1369 break; 1370 } 1371 1372 sal_usleep(poll_interval_uSec); 1373 poll_period_uSec -= poll_interval_uSec; 1374 } 1375 } 1376 1377 _bcm_esw_get_timestamp(unit, gdpll_chan.event_fb.ts_counter, &TS); 1378 1379 /* 1380 * Setup procedure for 1A 1381 * 1. Read current 52b Timestamp counter, say T 1382 * 2. Compute C as under 1383 * R = floor((T >> 4) / 1e7) 1384 * C = (R*1e7 + 1e9) mod 2^48 1385 * 3. Initialize phase counter to "C << 4" 1386 */ 1387 u64_H(mask_bit) = 0; 1388 u64_L(mask_bit) = 10000000; 1389 1390 COMPILER_64_SHR(TS, 4); 1391 COMPILER_64_UDIV_64(TS, mask_bit); 1392 COMPILER_64_UMUL_32(TS, 10000000); 1393 COMPILER_64_ADD_32(TS, 1000000000); 1394 1395 u64_H(mask_bit) = 0xFFFF; 1396 u64_L(mask_bit) = 0xFFFFFFFF; 1397 COMPILER_64_AND(TS, mask_bit); 1398 COMPILER_64_SHL(TS, 4); 1399 1400 COMPILER_64_COPY(gdpll_chan.chan_dpll_state.phase_counter, TS); 1401 COMPILER_64_COPY(offset, TS); 1402 1403 #ifdef CPRIMOD_SUPPORT 1404 cpriPort = gdpll_chan.event_fb.port; 1405 COMPILER_64_ADD_32(offset, 1066656); /* i.e, 66667 << 4 */ 1406 _bcm_future_cpri_enable(unit, cpriPort, offset); 1407 #endif 1408 } 1409 } else if (use_case_flag == 2) { 1410 1411 /* use-case 1E */ 1412 cli_out("### GDPLL DIAG: use_case 1E config\n"); 1413 bcn_update = 1; 1414 result = bcm_gdpll_cb_register(unit, BCM_GDPLL_CB_RSVD1, bcm_gdpll_cb_rsvd1, NULL); 1415 if (BCM_FAILURE(result)) { 1416 return CMD_FAIL; 1417 } 1418 } else if (use_case_flag == 3) { 1419 /* use-case 1D */ 1420 uint32 busy_wait = 10; /* uSec wait per cycle */ 1421 uint32 wait_period = 20*1000/busy_wait; /* 20mSec */ 1422 1423 cli_out("### GDPLL DIAG: use_case 1D(Option2) config\n"); 1424 1425 /* Flag for callback function to update TS */ 1426 ts_update = 1; 1427 result = bcm_gdpll_cb_register(unit, BCM_GDPLL_CB_RSVD1, bcm_gdpll_cb_rsvd1, NULL); 1428 if (BCM_FAILURE(result)) { 1429 return CMD_FAIL; 1430 } 1431 1432 while (ts_update) { 1433 sal_usleep(busy_wait); 1434 wait_period--; 1435 1436 if (wait_period == 0) { 1437 cli_out("### Error !! TS counter not updated with latest RP1\n"); 1438 return CMD_FAIL; 1439 } 1440 } 1441 1442 /* Set the phase_counter */ 1443 u64_H(gdpll_chan.chan_dpll_state.phase_counter) = u64_H(ts52b); 1444 u64_L(gdpll_chan.chan_dpll_state.phase_counter) = u64_L(ts52b); 1445 1446 cli_out("### phase_counter : u:0x%x l:0x%x\n", 1447 u64_H(gdpll_chan.chan_dpll_state.phase_counter), 1448 u64_L(gdpll_chan.chan_dpll_state.phase_counter)); 1449 1450 } else if (use_case_flag == 4) { 1451 /* use-case 1g */ 1452 uint32 ts_gpio = 0; 1453 uint64 ts_reset = 0; 1454 uint64 mask_bit; 1455 int gpsToD = 0; 1456 uint32 pToD = ToD_LOCATION; 1457 char tod_buffer[ToD_BUFFER_LENGTH]; 1458 uint32 val, val1, i; 1459 char mydate[12]; 1460 char mytime[10]; 1461 #if defined(GDPLL_SAL_HAS_TIME) 1462 uint32_t/*time_t*/ time; 1463 #endif 1464 1465 tod_buffer[0] = '\0'; 1466 pps_detect = 0; 1467 1468 cli_out("### GDPLL DIAG: use_case 1G config\n"); 1469 1470 c = ARG_GET(args); 1471 if ((c != NULL) && parse_cmp("SyncGPSToD", c, 0)) { 1472 cli_out("### GDPLL DIAG: This option is only for DEMO\n"); 1473 cli_out(" Setup:\n"); 1474 cli_out(" 1. Ensure that the R5 FW is loaded, that acts as the GPS source\n"); 1475 cli_out(" 2. Host polls the ToD from GPS to be programmed to TS counter\n"); 1476 1477 /* Sanity check if the ToD is coming ??? */ 1478 sal_usleep(1000*1000*2); /* To check the ToD count incrementing */ 1479 1480 val = soc_cm_iproc_read(unit, ToD_LOCATION_AVAIL); 1481 sal_usleep(1000*1000*3); /* Wait for 5 sec to check the ToD count */ 1482 val1 = soc_cm_iproc_read(unit, ToD_LOCATION_AVAIL); 1483 if (val1 != val) { 1484 cli_out("### GDPLL DIAG: GPS-ToD Available\n"); 1485 gpsToD = 1; 1486 } else { 1487 cli_out("### GDPLL DIAG: Error, ToD NOT Available. Please check R5-FW val:%d val1:%d\n", val, val1); 1488 return CMD_FAIL; 1489 } 1490 } else if (c != NULL) { 1491 cli_out("### GDPLL DIAG: Invalid command\n"); 1492 return CMD_FAIL; 1493 } 1494 1495 /* Disable the timestamper */ 1496 _bcm_esw_timestamp_enable(unit, gdpll_chan.event_fb.ts_counter, 0); 1497 1498 u64_H(ts_reset) = 0; u64_L(ts_reset) = 0; 1499 _bcm_esw_set_timestamp(unit, gdpll_chan.event_fb.ts_counter, ts_reset); 1500 1501 poll_period_uSec = 30*60*1000000; /* Poll for 30mins */ 1502 poll_interval_uSec = 1; 1503 1504 if ((gdpll_chan.event_fb.input_event == bcmGdpllInputEventBS0HB) || 1505 (gdpll_chan.event_fb.input_event == bcmGdpllInputEventBS1HB)) { 1506 cli_out(" 1PPS input on BS%d-HB configured in INPUT-Mode !!!\n", 1507 gdpll_chan.event_fb.input_event-bcmGdpllInputEventBS0HB); 1508 1509 /* Set BS Input-Mode and Enable-Capture */ 1510 if (gdpll_chan.event_fb.input_event == bcmGdpllInputEventBS0HB) { 1511 SOC_IF_ERROR_RETURN(READ_NS_BS0_BS_CONFIGr(unit, &rval)); 1512 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, &rval, MODEf, 0); 1513 SOC_IF_ERROR_RETURN(WRITE_NS_BS0_BS_CONFIGr(unit, rval)); 1514 1515 SOC_IF_ERROR_RETURN(READ_NS_MISC_CLK_EVENT_CTRLr(unit, &rval)); 1516 rval = rval | 0x2; 1517 SOC_IF_ERROR_RETURN(WRITE_NS_MISC_CLK_EVENT_CTRLr(unit, rval)); 1518 1519 } else { 1520 SOC_IF_ERROR_RETURN(READ_NS_BS1_BS_CONFIGr(unit, &rval)); 1521 soc_reg_field_set(unit, NS_BS1_BS_CONFIGr, &rval, MODEf, 0); 1522 SOC_IF_ERROR_RETURN(WRITE_NS_BS1_BS_CONFIGr(unit, rval)); 1523 1524 SOC_IF_ERROR_RETURN(READ_NS_MISC_CLK_EVENT_CTRLr(unit, &rval)); 1525 rval = rval | 0x4; 1526 SOC_IF_ERROR_RETURN(WRITE_NS_MISC_CLK_EVENT_CTRLr(unit, rval)); 1527 } 1528 1529 poll_period_uSec = 30*60*1000000; /* Poll for 30mins */ 1530 poll_interval_uSec = 1; /* Poll for every 1uSec */ 1531 1532 /* Poll on the next 1PPS event */ 1533 while(poll_period_uSec > 0) { 1534 SOC_IF_ERROR_RETURN(READ_NS_MISC_EVENT_STATUSr(unit, &rval)); 1535 if (((gdpll_chan.event_fb.input_event == bcmGdpllInputEventBS0HB) && 1536 soc_reg_field_get(unit, NS_MISC_EVENT_STATUSr, rval, BS0_HEARTBEATf)) || 1537 ((gdpll_chan.event_fb.input_event == bcmGdpllInputEventBS1HB) && 1538 soc_reg_field_get(unit, NS_MISC_EVENT_STATUSr, rval, BS1_HEARTBEATf))) { 1539 1540 pps_detect = 1; 1541 break; 1542 } 1543 sal_usleep(poll_interval_uSec); 1544 poll_period_uSec -= poll_interval_uSec; 1545 } 1546 1547 } else if((gdpll_chan.event_fb.input_event == bcmGdpllInputEventGPIO0) || 1548 (gdpll_chan.event_fb.input_event == bcmGdpllInputEventGPIO1) || 1549 (gdpll_chan.event_fb.input_event == bcmGdpllInputEventGPIO2) || 1550 (gdpll_chan.event_fb.input_event == bcmGdpllInputEventGPIO3) || 1551 (gdpll_chan.event_fb.input_event == bcmGdpllInputEventGPIO4) || 1552 (gdpll_chan.event_fb.input_event == bcmGdpllInputEventGPIO5)) { 1553 1554 /* Find the input TS_GPIO */ 1555 ts_gpio = gdpll_chan.event_fb.input_event - bcmGdpllInputEventGPIO0; 1556 if (ts_gpio < 0 || ts_gpio > 5) { 1557 cli_out("Error: Wrong GPIO input %d !!!\n", gdpll_chan.event_fb.input_event); 1558 return CMD_FAIL; 1559 } 1560 cli_out(" 1PPS input on TS_GPIO%d !!!\n", ts_gpio); 1561 1562 /* Poll on the next 1PPS event */ 1563 while(poll_period_uSec > 0) { 1564 SOC_IF_ERROR_RETURN(READ_NS_MISC_EVENT_STATUSr(unit, &rval)); 1565 if (((ts_gpio == 0) && soc_reg_field_get(unit, NS_MISC_EVENT_STATUSr, rval, TS_GPIO_0f)) || 1566 ((ts_gpio == 1) && soc_reg_field_get(unit, NS_MISC_EVENT_STATUSr, rval, TS_GPIO_1f)) || 1567 ((ts_gpio == 2) && soc_reg_field_get(unit, NS_MISC_EVENT_STATUSr, rval, TS_GPIO_2f)) || 1568 ((ts_gpio == 3) && soc_reg_field_get(unit, NS_MISC_EVENT_STATUSr, rval, TS_GPIO_3f)) || 1569 ((ts_gpio == 4) && soc_reg_field_get(unit, NS_MISC_EVENT_STATUSr, rval, TS_GPIO_4f)) || 1570 ((ts_gpio == 5) && soc_reg_field_get(unit, NS_MISC_EVENT_STATUSr, rval, TS_GPIO_5f))) { 1571 1572 pps_detect = 1; 1573 break; 1574 } 1575 sal_usleep(poll_interval_uSec); 1576 poll_period_uSec -= poll_interval_uSec; 1577 } 1578 } 1579 1580 if (!pps_detect) { 1581 cli_out("Error: No 1PPS signal detected !!!\n"); 1582 return CMD_FAIL; 1583 } 1584 1585 if (gpsToD) { 1586 /* ToD read from R5 is in NMEA format, "$GPZDA,055559.00,15,10,2018" */ 1587 pToD = ToD_LOCATION; 1588 1589 for (i=0; i < ToD_BUFFER_LENGTH; i+=4, pToD+=4) { 1590 val = soc_cm_iproc_read(unit, pToD); 1591 tod_buffer[i] = 0xFF & val; 1592 tod_buffer[i+1] = 0xFF & (val>>8); 1593 tod_buffer[i+2] = 0xFF & (val>>16); 1594 tod_buffer[i+3] = 0xFF & (val>>24); 1595 } 1596 1597 /*cli_out("### GDPLL DIAG: ToD- %s\n", tod_buffer);*/ 1598 if (tod_buffer[0] == '$') { 1599 /* ToD read from R5, NMEA format is "$GPZDA,055559.00,15,10,2018" */ 1600 1601 /* Date in YYYY-MM-DD format */ 1602 mydate[0]=tod_buffer[23]; mydate[1]=tod_buffer[24]; mydate[2]=tod_buffer[25]; mydate[3]=tod_buffer[26]; 1603 mydate[4]='-'; 1604 mydate[5]=tod_buffer[20]; mydate[6]=tod_buffer[21]; 1605 mydate[7]='-'; 1606 mydate[8]=tod_buffer[17]; mydate[9]=tod_buffer[18]; 1607 mydate[10]='\0'; 1608 1609 /* Time in HH:MM:SS format */ 1610 mytime[0]= tod_buffer[7]; mytime[1]= tod_buffer[8]; 1611 mytime[2]=':'; 1612 mytime[3]= tod_buffer[9]; mytime[4]= tod_buffer[10]; 1613 mytime[5]=':'; 1614 mytime[6]= tod_buffer[11]; mytime[7]= tod_buffer[12]; 1615 mytime[8]='\0'; 1616 1617 cli_out("### GDPLL DIAG: ToD-format: $GPZDA,055559.00,15,10,2018\n"); 1618 1619 } else if (tod_buffer[0] == '#') { 1620 /* ToD read from R5, format is custom format, "#51,10242018,130840" */ 1621 int start; 1622 1623 /* Date in YYYY-MM-DD format */ 1624 start = 8; 1625 mydate[0]=tod_buffer[start]; mydate[1]=tod_buffer[start+1]; mydate[2]=tod_buffer[start+2]; mydate[3]=tod_buffer[start+3]; 1626 mydate[4]='-'; 1627 start = 4; 1628 mydate[5]=tod_buffer[start]; mydate[6]=tod_buffer[start+1]; 1629 mydate[7]='-'; 1630 mydate[8]=tod_buffer[start+2]; mydate[9]=tod_buffer[start+3]; 1631 mydate[10]='\0'; 1632 1633 /* Time in HH:MM:SS format */ 1634 start = 13; 1635 mytime[0]= tod_buffer[start]; mytime[1]= tod_buffer[start+1]; 1636 mytime[2]=':'; 1637 mytime[3]= tod_buffer[start+2]; mytime[4]= tod_buffer[start+3]; 1638 mytime[5]=':'; 1639 mytime[6]= tod_buffer[start+4]; mytime[7]= tod_buffer[start+5]; 1640 mytime[8]='\0'; 1641 1642 cli_out("### GDPLL DIAG: ToD-format: #51,10242018,130840\n"); 1643 } 1644 cli_out("### GDPLL DIAG: myTime:%s myDate:%s\n", mytime, mydate); 1645 1646 #if defined(GDPLL_SAL_HAS_TIME) 1647 time = (uint32_t)get_time(mydate, mytime); 1648 1649 /* Conver time to 52b timestamp format and program to TS counter here 1650 * Assume a as a Linux epoch timestamp 1651 * int64 b = (a* 1000000000LL) & 0xffffffffffffLL; - convert to 48 bit nanoseconds 1652 * b = b << 4; - Convert to 52 bit Monterey format 1653 */ 1654 1655 /* 48b mask */ 1656 u64_H(mask_bit) = 0xFFFF; 1657 u64_L(mask_bit) = 0xFFFFFFFF; 1658 1659 u64_H(ts_reset) = 0; u64_L(ts_reset) = time; 1660 COMPILER_64_UMUL_32(ts_reset, 1000000000); 1661 COMPILER_64_AND(ts_reset, mask_bit); 1662 COMPILER_64_SHL(ts_reset, 4); 1663 1664 /* Program TS counter and phase-counter */ 1665 _bcm_esw_set_timestamp(unit, gdpll_chan.event_fb.ts_counter, ts_reset); 1666 COMPILER_64_COPY(gdpll_chan.chan_dpll_state.phase_counter, ts_reset); 1667 cli_out("### GDPLL DIAG: GPS tick:%d, phase_counter: 0x%x 0x%x\n", 1668 time, u64_H(ts_reset), u64_L(ts_reset)); 1669 #else 1670 cli_out("### GDPLL DIAG: Error!! No TIMEconversion functions for %s %s\n", mydate, mytime); 1671 return CMD_FAIL; 1672 #endif 1673 } 1674 1675 /* Enable the timestamper */ 1676 _bcm_esw_timestamp_enable(unit, gdpll_chan.event_fb.ts_counter, 1); 1677 1678 } else if (use_case_flag == 5) { 1679 /* use-case 2d */ 1680 int rv = BCM_E_NONE; 1681 1682 cli_out("### GDPLL DIAG: use_case 2D config\n"); 1683 1684 port_out = gdpll_chan.port; 1685 if ((rv = bcm_rx_register(unit, "GdpllROEFrame", roe_pkt_cb_handler, 1686 101/*0*/, NULL, /*BCM_RCO_F_INTR |*/ BCM_RCO_F_ALL_COS)) < 0) 1687 { 1688 cli_out("### GDPLL: bcm_rx_register failed: %s\n", bcm_errmsg(rv)); 1689 return(CMD_USAGE); 1690 } 1691 cli_out("### GDPLL: bcm_rx_register Success\n"); 1692 } else if (use_case_flag == 6) { 1693 1694 /* use-case: BS synthesizer */ 1695 uint64 T, V, val_64b; 1696 uint64 mask_bit; 1697 int rv = BCM_E_NONE; 1698 bcm_time_ts_counter_t counter; 1699 1700 cli_out("### GDPLL DIAG: BS Synthesizer config\n"); 1701 1702 /* Get the current 52b timestamper value */ 1703 counter.ts_counter=gdpll_chan.event_fb.ts_counter; 1704 rv = bcm_time_ts_counter_get(unit, &counter); 1705 if (rv != BCM_E_NONE) { 1706 cli_out("### Error in bcm_time_ts_counter_get\n"); 1707 return CMD_FAIL; 1708 } 1709 COMPILER_64_COPY(T, counter.ts_counter_ns); 1710 1711 /* V = floor(T / 16,000,000,000) */ 1712 COMPILER_64_COPY(V, T); 1713 COMPILER_64_SET(val_64b, 0x3, 0xB9ACA000); /* 16,000,000,000 = 0x3_B9AC_A000 */ 1714 COMPILER_64_UDIV_64(V, val_64b); 1715 1716 /* M = ((V+1)*16,000,000,000 - 1,600,000) Mod 2^52 */ 1717 COMPILER_64_ADD_32(V, 1); 1718 COMPILER_64_UMUL_32(V, 1000000000); 1719 COMPILER_64_SHL(V, 4); 1720 COMPILER_64_SUB_32(V, 1600000); 1721 1722 /* 52b mask for Mod 2^52 */ 1723 u64_H(mask_bit) = 0xFFFFF; 1724 u64_L(mask_bit) = 0xFFFFFFFF; 1725 1726 COMPILER_64_AND(V, mask_bit); 1727 COMPILER_64_COPY(gdpll_chan.chan_dpll_state.phase_counter, V); 1728 1729 /* Minimize the initial phase error 1730 * if ((phase_counter - TS) > 1mSec) then sleep(phase_counter - TS - 1mSec) 1731 */ 1732 COMPILER_64_SET(val_64b, 0, 1000000); /* 1mSec = 1000000nSec */ 1733 COMPILER_64_SHR(V, 4); 1734 COMPILER_64_SHR(T, 4); 1735 COMPILER_64_SUB_64(V, T); 1736 if (COMPILER_64_GT(V, val_64b)) { 1737 COMPILER_64_SUB_64(V, val_64b); 1738 COMPILER_64_UDIV_32(V, 1000); 1739 sal_usleep(u64_L(V)); 1740 } 1741 1742 } else if ((use_case_flag == 7) || (use_case_flag == 8)) { 1743 1744 /* use-case: 1N/1P */ 1745 uint64 secs, div, nano_secs; 1746 bcm_time_spec_t ts; 1747 bcm_time_ts_counter_t counter; 1748 int prog_phase_counter = 0; 1749 1750 cli_out("### GDPLL DIAG: use_case 1N config\n"); 1751 1752 poll_period_uSec = 30*60*1000000; /* Poll for 30mins */ 1753 poll_interval_uSec = 100000; /* Poll for every 100000uSec=100mSec */ 1754 1755 counter.ts_counter = gdpll_chan.event_fb.ts_counter; 1756 while(poll_period_uSec > 0) { 1757 1758 BCM_IF_ERROR_RETURN(bcm_time_ts_counter_get(unit, &counter)); 1759 1760 /* MO: Remove sub-ns portion */ 1761 COMPILER_64_SHR(counter.ts_counter_ns, 4); 1762 1763 1764 if (use_case_flag == 7) { 1765 COMPILER_64_SUB_32(counter.ts_counter_ns, 500000000); 1766 } else if (use_case_flag == 8) { 1767 COMPILER_64_SUB_32(counter.ts_counter_ns, 463000000); 1768 } 1769 1770 /* Get seconds from the timestamp value */ 1771 COMPILER_64_COPY(secs, counter.ts_counter_ns); 1772 COMPILER_64_SET(div, 0, 1000000000); 1773 COMPILER_64_UDIV_64(secs, div); 1774 COMPILER_64_SET(ts.seconds, 0, COMPILER_64_LO(secs)); 1775 1776 /* Get nanoseconds from the timestamp value */ 1777 COMPILER_64_COPY(nano_secs, counter.ts_counter_ns); 1778 COMPILER_64_UMUL_32(secs, 1000000000); 1779 COMPILER_64_SUB_64(nano_secs, secs); 1780 ts.nanoseconds = COMPILER_64_LO(nano_secs); 1781 1782 /* Bound check for the DPLL setup */ 1783 if ((ts.nanoseconds < 800000000) && (ts.nanoseconds > 600000000)) { 1784 prog_phase_counter = 1; 1785 break; 1786 } 1787 1788 sal_usleep(poll_interval_uSec); 1789 poll_period_uSec -= poll_interval_uSec; 1790 } 1791 1792 if (!prog_phase_counter) { 1793 cli_out("Error: 1n: Could not program phase counter !!!\n"); 1794 return CMD_FAIL; 1795 } 1796 1797 #ifdef NTP_PTP_DEBUG 1798 /* 1799 * Enable this, for testing/ensuring the 1st ON_SEC pulse after 1800 * 500mSec/537mSec for NTP/PTP ToD counter respectively as explained above 1801 */ 1802 ts.nanoseconds = 0; /* ### Just for testing */ 1803 cli_out("### 1N/1P: ts.seconds: 0x%x 0x%x\n", COMPILER_64_HI(ts.seconds), COMPILER_64_LO(ts.seconds)); 1804 cli_out("### 1N/1P: ts.nanoseconds: 0x%x\n", ts.nanoseconds); 1805 #endif 1806 if (use_case_flag == 7) { 1807 /* Program the NTP counter */ 1808 _bcm_program_ptpntptod(unit, ts, ToD_TYPE_NTP); 1809 } else if (use_case_flag == 8) { 1810 /* Program the PTP counter */ 1811 _bcm_program_ptpntptod(unit, ts, ToD_TYPE_PTP); 1812 } 1813 1814 /* Program the phase counter per spec */ 1815 COMPILER_64_ADD_32(ts.seconds, 1); 1816 COMPILER_64_UMUL_32(ts.seconds, 1000000000); 1817 COMPILER_64_SHL(ts.seconds, 4); 1818 COMPILER_64_COPY(gdpll_chan.chan_dpll_state.phase_counter, ts.seconds); 1819 /* cli_out("### 1N: phase_counter: 0x%x 0x%x\n", COMPILER_64_HI(gdpll_chan.chan_dpll_state.phase_counter), 1820 COMPILER_64_LO(gdpll_chan.chan_dpll_state.phase_counter)); */ 1821 } 1822 1823 if (flags & BCM_GDPLL_CHAN_ALLOC) { 1824 chan = 0xFF; 1825 } else { 1826 /* User should have passed the channel number */ 1827 c = ARG_GET(args); 1828 if (!isint(c)) { 1829 cli_out("%s: Error: Channel number \n", ARG_CMD(args)); 1830 return(CMD_USAGE); 1831 } 1832 chan = parse_integer(c); 1833 } 1834 #ifdef GDPLL_DEBUG 1835 if (disable_debug_log) { 1836 dump_chan_param(&gdpll_chan); 1837 } 1838 #endif 1839 result = bcm_gdpll_chan_create (unit, flags, &gdpll_chan, &chan); 1840 if (BCM_FAILURE(result)) { 1841 cli_out("Command failed. %s\n", bcm_errmsg(result)); 1842 return CMD_FAIL; 1843 } 1844 cli_out("Channel: %d\n", chan); 1845 1846 } else { 1847 cli_out("%s: Error: Channel command\n", ARG_CMD(args)); 1848 return(CMD_USAGE); 1849 } 1850 } else { 1851 cli_out("%s: Error: GDPLL command\n", ARG_CMD(args)); 1852 return(CMD_USAGE); 1853 } 1854 1855 return CMD_OK; 1856 } 1857 #endif