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

mcs.c (37766B)


      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: 	mcs.c
      8  * Purpose: 	Micro Controller Subsystem Support
      9  */
     10 
     11 #include <assert.h>
     12 #include <sal/core/libc.h>
     13 #include <shared/bsl.h>
     14 #include <bcm/error.h>
     15 #include <soc/types.h>
     16 #include <soc/dma.h>
     17 #if defined(BCM_JERICHO_SUPPORT)
     18 #include <soc/dpp/JER/jer_drv.h>
     19 #endif
     20 #include <appl/diag/shell.h>
     21 #include <appl/diag/system.h>
     22 #include <appl/diag/diag_mcs.h>
     23 
     24 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_IPROC_SUPPORT)
     25 
     26 #include <soc/uc.h>
     27 #include <soc/iproc.h>
     28 #include <soc/shared/mos_coredump.h>
     29 #include <soc/uc_msg.h>
     30 #include <soc/uc_dbg.h>
     31 
     32 extern void format_uint64_decimal(char *buf, uint64 n, int comma);
     33 uKernel_info_t fwInfo[MAX_UCS];
     34 
     35 void dumpbuf(uint8 *buf, int count) {
     36     int i;
     37     uint8 *bp = buf;
     38     for(i = 0; i < count; i++) {
     39         cli_out("%02X", *bp++);
     40         if ((i % 16) == 15) {
     41             cli_out("\n");
     42         }
     43     }
     44 }
     45 
     46 #ifndef NO_FILEIO
     47 
     48 #define DUMP_BUFFER_SIZE 1024
     49 
     50 STATIC cmd_result_t
     51 _mcs_dump_region(int unit, FILE *fp, uint32 *buffer, mos_coredump_region_t *reg) {
     52 
     53     uint32 addr = reg->baseaddr;
     54     uint32 len = reg->end - reg->start;
     55     int buf_idx = 0;
     56     while (len > 0) {
     57         buffer[buf_idx] = soc_uc_mem_read(unit, addr);
     58 
     59         len -= sizeof(uint32);
     60         addr += sizeof(uint32);
     61 
     62         /* Flush buffer to disk if it is full, or we are done with the region */
     63         if (++buf_idx >= (DUMP_BUFFER_SIZE / sizeof(uint32)) || (len == 0)) {
     64             if (sal_fwrite(buffer, 4, buf_idx, fp) != buf_idx) {
     65                 return(CMD_FAIL);
     66             }
     67             buf_idx = 0;
     68         }
     69     } 
     70 
     71     return (CMD_OK);
     72 }
     73 
     74 STATIC cmd_result_t
     75 mcs_dump(int unit, FILE *fp, int addr, int mem_size)
     76 {
     77     /* Set up the region */
     78     mos_coredump_region_t reg;
     79     uint32 *buffer;
     80 
     81     /* Init the regions descriptors */
     82         reg.cores = 1;
     83         reg.baseaddr = addr;
     84         reg.start = addr;
     85         reg.end = reg.start + mem_size;
     86 
     87     /* allocate 1k for data */
     88     buffer = (uint32 *) soc_cm_salloc(unit, DUMP_BUFFER_SIZE, "MCS Dump Buffer");
     89     if(buffer == NULL) {
     90         cli_out("Unable to allocate buffer\n");
     91         return(CMD_FAIL);
     92     }
     93 
     94     /* Write the desriptors */
     95     sal_memcpy(buffer, &reg, sizeof(mos_coredump_region_t));
     96     /* Ensure that descriptors are in network byte order */
     97     buffer[0] = soc_htonl(buffer[0]);
     98 
     99     if (sal_fwrite(buffer, sizeof(mos_coredump_region_t), 1, fp) != 1) {
    100         cli_out("Error writing header\n");
    101         return(CMD_FAIL);
    102     }
    103 
    104     if (_mcs_dump_region(unit, fp, buffer, &reg) != CMD_OK) {
    105         cli_out("Error writing dump\n");
    106         return(CMD_FAIL);
    107     }
    108 
    109     soc_cm_sfree(unit, buffer);
    110     
    111     return(CMD_OK);
    112 }
    113 
    114 uint32 ihex_ext_addr[SOC_MAX_NUM_DEVICES]; /* Extended Address */
    115 
    116 
    117 /*
    118  * returs -1 if error
    119  * returns number of bytes. (0 if this record doesn't contain any data).
    120  */
    121 STATIC int
    122 mcs_parse_ihex_record(int unit, char *line, uint32 *off)
    123 {
    124     int count;
    125     uint32 address;
    126 
    127     switch (line[8]) {      /* Record Type */
    128         case '0' :      /* Data Record */
    129             count = (xdigit2i(line[1]) << 4) |
    130                     (xdigit2i(line[2]));
    131 
    132             address = (xdigit2i(line[3]) << 12) |
    133                       (xdigit2i(line[4]) << 8) |
    134                       (xdigit2i(line[5]) << 4) |
    135                       (xdigit2i(line[6]));
    136 
    137             *off = ihex_ext_addr[unit] + address;
    138             return count;
    139             break; /* Not Reachable */
    140         case '4' :      /* Extended Linear Address Record */
    141             address = (xdigit2i(line[9]) << 12) |
    142                       (xdigit2i(line[10]) << 8) |
    143                       (xdigit2i(line[11]) << 4) |
    144                       (xdigit2i(line[12]));
    145 
    146             ihex_ext_addr[unit] = (address << 16);
    147             cli_out("Exteded Linear Address 0x%x\n", ihex_ext_addr[unit]);
    148             return 0;
    149             break; /* Not Reachable */
    150         default :       /* We don't parse all other records */
    151             cli_out("Unsupported Record\n");
    152             return 0;
    153     }
    154     return -1; /* Why are we here? */ /* Not Reachable */
    155 }
    156 
    157 STATIC int
    158 mcs_parse_srec_record (int unit, char *line, uint32 *off)
    159 {
    160     int count;
    161     uint32 address;
    162 
    163     switch (line[1]) {      /* Record Type */
    164         case '0':           /* Header record - ignore */
    165             return 0;
    166             break; /* Not Reachable */
    167             
    168         case '1' :          /* Data Record with 2 byte address */
    169             count = (xdigit2i(line[2]) << 4) |
    170                     (xdigit2i(line[3]));
    171             count -= 3; /* 2 address + 1 checksum */
    172 
    173             address = (xdigit2i(line[4]) << 12) |
    174                       (xdigit2i(line[5]) << 8) |
    175                       (xdigit2i(line[6]) << 4) |
    176                       (xdigit2i(line[7]));
    177 
    178             *off = address;
    179             return count;
    180             break; /* Not Reachable */
    181 
    182         case '2' :          /* Data Record with 3 byte address */
    183             count = (xdigit2i(line[2]) << 4) |
    184                     (xdigit2i(line[3]));
    185             count -= 4; /* 3 address + 1 checksum */
    186 
    187             address = (xdigit2i(line[4]) << 20) |
    188                       (xdigit2i(line[5]) << 16) |
    189                       (xdigit2i(line[6]) << 12) |
    190                       (xdigit2i(line[7]) << 8) |
    191                       (xdigit2i(line[8]) << 4) |
    192                       (xdigit2i(line[9]));
    193 
    194             *off = address;
    195             return count;
    196             break; /* Not Reachable */
    197 
    198         case '3' :          /* Data Record with 4 byte address */
    199             count = (xdigit2i(line[2]) << 4) |
    200                     (xdigit2i(line[3]));
    201             count -= 5; /* 4 address + 1 checksum */
    202 
    203             address = (xdigit2i(line[4]) << 28) |
    204                       (xdigit2i(line[5]) << 24) |
    205                       (xdigit2i(line[6]) << 20) |
    206                       (xdigit2i(line[7]) << 16) |
    207                       (xdigit2i(line[8]) << 12) |
    208                       (xdigit2i(line[9]) << 8) |
    209                       (xdigit2i(line[10]) << 4) |
    210                       (xdigit2i(line[11]));
    211 
    212             *off = address;
    213             return count;
    214             break; /* Not Reachable */
    215             
    216         case '5':         /* Record count - ignore */
    217         case '6':         /* End of block - ignore */
    218         case '7':         /* End of block - ignore */
    219         case '8':         /* End of block - ignore */
    220         case '9':         /* End of block - ignore */
    221             return 0;
    222             break; /* Not Reachable */
    223             
    224         default :       /* We don't parse all other records */
    225             cli_out("Unsupported Record S%c\n", line[1]);
    226             return 0;
    227     }
    228     return -1; /* Why are we here? */ /* Not Reachable */
    229 }
    230 
    231 
    232 /*
    233  * It is assumed that by the time this routine is called
    234  * the record is already validated. So, blindly get data
    235  */
    236 STATIC void
    237 mcs_get_rec_data(char *line, int count, uint8 *dat)
    238 {
    239     int i, datpos = 9;  /* 9 is valid for ihex */
    240 
    241     if (!count) {
    242         return;
    243     }
    244 
    245     if (line[0] != ':') {
    246         /* not ihex */
    247         switch (line[1]) {
    248         case '1':  /* S1 record */
    249             datpos = 8;
    250             break;
    251         case '2':  /* S2 record */
    252             datpos = 10;
    253             break;
    254         case '3':  /* S3 record */
    255             datpos = 12;
    256             break;
    257         default:
    258             cli_out("Unexpected record type: '%c'\n", line[1]);
    259             SOC_CMIC_UCDBG_LOG_ADD((0, _bcmCmicUcDbgLogHostMcsLoad,
    260                 "%s: Unexpected record type\n", FUNCTION_NAME()));
    261             break;
    262         }
    263     }
    264 
    265     /*1 count = 2 hex chars */
    266     for(i = 0; i < count; i++) {
    267         *(dat + i) = ((xdigit2i(line[datpos + (i * 2)])) << 4) |
    268                     (xdigit2i(line[datpos + (i * 2) + 1]));
    269     }
    270 }
    271 
    272 STATIC cmd_result_t
    273 mcs_file_load(int unit, FILE *fp, int ucnum, uint32 *lowaddr, int stage, uint32 twostageaddr)
    274 {
    275     uint32 addr=0;
    276     int rv = 0;
    277     char input[256], *cp = NULL;
    278     unsigned char data[256];
    279 
    280     if (lowaddr != NULL) {
    281         *lowaddr = 0xffff0000;
    282     }
    283     ihex_ext_addr[unit] = 0; /* Until an extended addr record is met.. */
    284 
    285     while (NULL != (cp = sal_fgets(input, sizeof(input) - 1, fp))) {
    286         if (input[0] == 'S') {
    287             rv = mcs_parse_srec_record(unit, cp, &addr);
    288         } else if (input[0] == ':') {
    289             rv = mcs_parse_ihex_record(unit, cp, &addr);
    290         } else {
    291             cli_out("unknown Record Type\n");
    292             SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostMcsLoad,
    293                 "%s: unknown Record Type\n", FUNCTION_NAME()));
    294             rv = -1;
    295         }
    296 
    297         if (-1 == rv) {
    298             return (CMD_FAIL);
    299         }
    300 
    301         if (rv % 4) {
    302             cli_out("record Not Multiple of 4\n");
    303             SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostMcsLoad,
    304                 "%s: record Not Multiple of 4\n", FUNCTION_NAME()));
    305             return (CMD_FAIL);
    306         }
    307 
    308         /* Do this only if first stage */        
    309         if (stage == 0) {
    310             /* track lowest seen address with data */
    311             if ((rv > 0) && (lowaddr != NULL) && (addr < *lowaddr)) {
    312                 *lowaddr = addr;
    313             }
    314         }
    315 
    316         if ((stage == 0) && (addr >= twostageaddr)) {
    317 		  /* No Need to parse teh remaining now... */
    318             return CMD_OK;
    319         }
    320 
    321         if ( ((stage == 0) && (addr < twostageaddr)) ||
    322              ((stage == 1) && (addr >= twostageaddr))) {
    323                 mcs_get_rec_data(cp, rv, data);
    324                 soc_uc_load(unit, ucnum, addr, rv, data);
    325         }
    326     }
    327     return(CMD_OK);
    328 }
    329 
    330 #endif
    331 
    332 
    333 char mcsload_usage[] =
    334     "Parameters: <uCnum> <file.hex>\n\t\t"
    335 #ifndef COMPILER_STRING_CONST_LIMIT    
    336     "[InitMCS|ResetUC|StartUC|StartMSG]=true|false]\n\t\t"
    337     "Load the MCS memory area from <file.srec>.\n\t"
    338     "uCnum = uC number to be loaded.\n\t"
    339     "InitMCS = Init the MCS (not just one UC) (false)\n\t"
    340     "ResetUC = Reset the uC (true)\n\t"
    341     "StartUC = uC out of halt after load (true)\n\t"
    342     "StartMSG = Start messaging (true)\n"
    343 #endif    
    344     ;
    345 
    346 cmd_result_t
    347 mcsload_cmd(int unit, args_t *a)
    348 /*
    349  * Function: 	mcsload_cmd
    350  * Purpose:	Load a file into MCS.
    351  * Parameters:	unit - unit
    352  *		a - args, each of the files to be displayed.
    353  * Returns:	CMD_OK/CMD_FAIL/CMD_USAGE
    354  */
    355 {
    356     cmd_result_t rv = CMD_OK;
    357     parse_table_t  pt;
    358     char *c , *filename;
    359     int ucnum, resetuc = 1, startuc=1, startmsg=1, initmcs = 0, twostage = 0;
    360     uint32 twostageaddr = 0xffffffff;
    361 
    362 #ifndef NO_FILEIO
    363 #ifndef NO_CTRL_C
    364     jmp_buf ctrl_c;
    365 #endif    
    366     FILE * volatile fp = NULL;
    367     uint32 lowaddr;
    368 #endif
    369 #ifdef BCM_SABER2_SUPPORT
    370     uint16 dev_id;
    371     uint8  rev_id;
    372 #endif
    373 
    374     if (!sh_check_attached("mcsload", unit)) {
    375         return(CMD_FAIL);
    376     }
    377 
    378     if (!soc_feature(unit, soc_feature_uc)) {
    379         return (CMD_FAIL);
    380     } 
    381 
    382     if (ARG_CNT(a) < 2) {
    383         return(CMD_USAGE);
    384     }
    385 
    386     c = ARG_GET(a);
    387     if (!isint(c)) {
    388         cli_out("%s: Error: uC Num not specified\n", ARG_CMD(a));
    389         return(CMD_USAGE);
    390     }
    391 
    392     ucnum = parse_integer(c);
    393     if (ucnum < 0 || ucnum >= SOC_INFO(unit).num_ucs) {
    394         cli_out("Invalid uProcessor number: %d\n", ucnum); 
    395         return(CMD_FAIL);
    396     }
    397 
    398     c = ARG_GET(a);
    399     filename = c;
    400     if (filename == NULL) {
    401         cli_out("%s: Error: No file specified\n", ARG_CMD(a));
    402         return(CMD_USAGE);
    403     }
    404 
    405     if (ARG_CNT(a) > 0) {
    406         parse_table_init(unit, &pt);
    407         parse_table_add(&pt, "InitMCS", PQ_DFL|PQ_BOOL,
    408                         0, &initmcs,  NULL);
    409         parse_table_add(&pt, "ResetUC", PQ_DFL|PQ_BOOL,
    410                         0, &resetuc,  NULL);
    411         parse_table_add(&pt, "StartUC", PQ_DFL|PQ_BOOL,
    412                         0, &startuc,  NULL);
    413         parse_table_add(&pt, "StartMSG", PQ_DFL|PQ_BOOL,
    414                         0, &startmsg,  NULL);
    415         parse_table_add(&pt, "TwoStage", PQ_DFL|PQ_BOOL,
    416                         0, &twostage,  NULL);
    417         parse_table_add(&pt, "TwoStageAddress", PQ_DFL|PQ_INT,
    418                         0, &twostageaddr, NULL);
    419         if (!parseEndOk(a, &pt, &rv)) {
    420             if (CMD_OK != rv) {
    421                 return rv;
    422             }
    423         }
    424     }
    425 
    426 #ifdef BCM_SABER2_SUPPORT
    427     /* mHost1 is disabled in dagger2 (BCM56233) */
    428     soc_cm_get_id(unit, &dev_id, &rev_id);
    429     if (SOC_IS_SABER2(unit) && (dev_id == BCM56233_DEVICE_ID) && (ucnum == 1)) {
    430         return(CMD_FAIL);
    431     }
    432 #endif
    433 
    434     if (twostage) {
    435         startuc = 1; /* Force Start */
    436     } else {
    437         twostageaddr = 0xffffffff;
    438     }
    439     
    440     /* check for simulation*/
    441     if (SAL_BOOT_BCMSIM) {
    442         return(rv);
    443     }
    444 
    445     /* initialize ukernel debug module */
    446     soc_cmic_ucdebug_init(unit, ucnum);
    447 
    448 
    449 #ifdef NO_FILEIO
    450     cli_out("no filesystem\n");
    451 #else
    452 #ifndef NO_CTRL_C    
    453     if (!setjmp(ctrl_c)) {
    454         sh_push_ctrl_c(&ctrl_c);
    455 #endif
    456 	/* See if we can open the file before doing anything else */
    457         fp = sal_fopen(filename, "r");
    458         if (!fp) {
    459             cli_out("%s: Error: Unable to open file: %s\n",
    460                     ARG_CMD(a), filename);
    461             SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostMcsLoad,
    462                 "Error: Unable to open file: %s\n", filename));
    463             rv = CMD_FAIL;
    464 #ifndef NO_CTRL_C    
    465             sh_pop_ctrl_c();
    466 #endif
    467             return rv;
    468         }
    469 
    470         /* Reset the UC to stop messages before stopping the msg system */
    471         if (resetuc || initmcs) {
    472             soc_uc_reset(unit, ucnum);
    473         }
    474 
    475         if (initmcs) {
    476             soc_uc_init(unit);
    477         }
    478             
    479         soc_uc_preload(unit, ucnum);
    480 
    481         rv = mcs_file_load(unit, fp, ucnum, &lowaddr, 0, twostageaddr);
    482 
    483         if (startuc) {
    484             soc_uc_start(unit, ucnum, lowaddr);
    485             sal_usleep(100 * 1000);
    486         }
    487 
    488 #if defined(BCM_IPROC_SUPPORT)
    489         if (twostage) {
    490             int retries;
    491             uint32 rval;
    492             rv = CMD_OK;
    493             if (soc_cm_get_bus_type(unit) & SOC_DEV_BUS_ALT) {
    494                 WRITE_PAXB_1_PCIE_EP_AXI_CONFIGr(unit, 0xfffdff7f);
    495             } else {
    496                 WRITE_PAXB_0_PCIE_EP_AXI_CONFIGr(unit, 0xfffdff7f);
    497             }
    498 
    499             cli_out("Waiting for Core-%d to start", ucnum);
    500             SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostMcsLoad,
    501                 "Waiting for Core-%d to start\n", ucnum));
    502             rval = 0;
    503             retries = 0;
    504             while (rval != 0x10c8ed) { /* Locked?? */
    505                 sal_usleep(10 * 1000);
    506                 rval = soc_cm_iproc_read(unit, 0x1b07f000);
    507                 cli_out(".");
    508                 if (++retries > 100) {
    509                     SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostMcsLoad,
    510                             "Error: Unable to start Core-%d rval:0x%x\n", 
    511                             ucnum, rval));
    512                     rv = CMD_FAIL;
    513                     break;
    514                 }
    515             }
    516             /* L2$ Cache has been Initialized */
    517 
    518             if (rv == CMD_OK) {
    519                 cli_out("\nWaiting for L2$ to be configured");
    520                 rval = 0;
    521                 retries = 0;
    522                 while (rval != 0xdeadc0de) {
    523                     sal_usleep(10 * 1000);
    524                     rval = soc_cm_iproc_read(unit, twostageaddr);
    525                     cli_out(".");
    526                     if (++retries > 100) {
    527                         SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostMcsLoad,
    528                          "Error: Waiting for L2$ to be configured rval: 0x%x\n",
    529                          rval));
    530                         rv = CMD_FAIL;
    531                         break;
    532                     }
    533                 }
    534                 cli_out("\n");
    535             }
    536             /* L2$ Cache has been configured as RAM */
    537 
    538             /* Last read was for first line of 2nd stage.  So close/reopen
    539                so that next load doesn't miss that line
    540             */
    541 
    542             sal_fclose((FILE *)fp);
    543             fp = NULL;
    544 
    545             if (rv != CMD_OK) {
    546                 /* Last Load failed: Timed Out */
    547 #ifndef NO_CTRL_C
    548                 sh_pop_ctrl_c();
    549 #endif
    550                 return rv;
    551             }
    552 
    553             fp = sal_fopen(filename, "r");
    554             if (!fp) {
    555                 cli_out("%s: Error: Unable to open file: %s\n",
    556                         ARG_CMD(a), filename);
    557                 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostMcsLoad,
    558                     "%s: Error: Unable to open file: %s\n",
    559                     ARG_CMD(a), filename));
    560                 rv = CMD_FAIL;
    561 #ifndef NO_CTRL_C
    562                 sh_pop_ctrl_c();
    563 #endif
    564                 return rv;
    565             }
    566 
    567             rv = mcs_file_load(unit, fp, ucnum, &lowaddr, 1, twostageaddr);
    568             soc_cm_iproc_write(unit, twostageaddr, 0x10aded); /*Loaded */
    569         }
    570 #endif /* IPROC_SUPPORT */
    571 
    572         sal_fclose((FILE *)fp);
    573         fp = NULL;
    574 
    575 #ifdef BCM_MONTEREY_SUPPORT
    576         /* In monterey ucnum:2 is M7 and no messaging required */
    577         if (!(SOC_IS_MONTEREY(unit) && (ucnum == 2))) {
    578 #endif
    579             if (startmsg) {
    580                 soc_cmic_uc_msg_start(unit);
    581                 soc_cmic_uc_msg_uc_start(unit, ucnum);
    582             }
    583 #ifdef BCM_MONTEREY_SUPPORT
    584         }
    585 #endif
    586 
    587 #ifndef NO_CTRL_C    
    588     } else if (fp) {
    589         sal_fclose((FILE *)fp);
    590         fp = NULL;
    591         rv = CMD_INTR;
    592     }
    593     sh_pop_ctrl_c();
    594 #endif    
    595 #endif /* NO_FILEIO */
    596     sal_usleep(10000);
    597 
    598     /* WA for "bus error" issue that SDK configure the RSVD field of 
    599      * MHOST_0_CR5_CFG_CTRL, then uKernel polling this register field to kill 
    600      * or stop the thread. 
    601      */
    602 #if defined(BCM_JERICHO_SUPPORT)
    603     if (SOC_IS_JERICHO(unit)) {
    604         soc_restore_bcm88x7x(unit, 0);
    605     }
    606 #endif
    607 
    608     return(rv);
    609 }
    610 
    611 char mcsdump_usage[] =
    612     "Parameters: [uCnum|<dumpfile>] <ADDR> <MEM_SIZE> [Halt=true|false]\n\t"
    613     "Dump both uCs memory in BRCM dumpfile format.\n\t"
    614     "<file.hex> = dumpfile to write.\n\t"
    615     "Halt = Halt the UCs prior to the dump.\n\t"
    616     "Address = Base address + Offset.\n\t"
    617     "Size of memory to be read.\n\t"
    618     "uCnum = uC core Cpu and Memory usage report \n";
    619 
    620 cmd_result_t
    621 mcsdump_cmd(int unit, args_t *a)
    622 /*
    623  * Function: 	mcsdump_cmd
    624  * Purpose:	Dump the MCS.
    625  * Parameters:	unit - unit
    626  *		a - args, each of the files to be displayed.
    627  * Returns:	CMD_OK/CMD_FAIL/CMD_USAGE
    628  */
    629 {
    630     cmd_result_t rv = CMD_OK;
    631     parse_table_t  pt;
    632     char *c , *filename;
    633     int halt = 0, ucnum = 0;
    634     uint32 reg0, reg1, regs;
    635     char *thread_info;
    636 #ifndef NO_FILEIO
    637     int addr, mem_size;
    638 #endif
    639 
    640 #ifndef NO_FILEIO
    641 #ifndef NO_CTRL_C
    642     jmp_buf ctrl_c;
    643 #endif
    644     FILE * volatile fp = NULL;
    645 #endif
    646 
    647     if (!sh_check_attached("mcsload", unit)) {
    648         return(CMD_FAIL);
    649     }
    650 
    651     /* CMICm only at the moment */
    652     if (!soc_feature(unit, soc_feature_uc)) {
    653         return (CMD_FAIL);
    654     } 
    655 
    656     if (ARG_CNT(a) < 1) {
    657         return(CMD_USAGE);
    658     }
    659 
    660     c = ARG_GET(a);
    661     if (isint(c)) {
    662         ucnum = parse_integer(c);
    663         if (ucnum < SOC_INFO(unit).num_ucs) {
    664             cli_out("ID         Name               %%       Base        Size        sp        free  Priority   run_time\n");
    665             thread_info = soc_uc_firmware_thread_info(unit, ucnum);
    666             if (thread_info) {
    667                 cli_out("%s\n", thread_info);
    668                 soc_cm_sfree(unit, thread_info);
    669             }
    670             return (CMD_OK);
    671         } else {
    672             cli_out("%s: Error: uC Num not legal\n", ARG_CMD(a));
    673             return(CMD_USAGE);
    674         }
    675     }
    676     filename = c;
    677     if (filename == NULL) {
    678         cli_out("%s: Error: No file specified\n", ARG_CMD(a));
    679         return(CMD_USAGE);
    680     }
    681 
    682 #ifndef NO_FILEIO
    683     if (ARG_CNT(a) < 2) {
    684         cli_out("%s: Error: provide valid address and size\n", ARG_CMD(a));
    685         return(CMD_USAGE);
    686     }
    687     c = ARG_GET(a);
    688     if (isint(c)) {
    689         addr = parse_integer(c);
    690         c = ARG_GET(a);
    691         if (isint(c)) {
    692             mem_size = parse_integer(c);
    693         } else {
    694             cli_out("%s: Error: provide memory size\n", ARG_CMD(a));
    695             return(CMD_USAGE);
    696         }
    697     } else {
    698         cli_out("%s: Error: provide base address\n", ARG_CMD(a));
    699         return(CMD_USAGE);
    700     }
    701 #endif
    702 
    703     parse_table_init(unit, &pt);
    704     parse_table_add(&pt, "Halt", PQ_DFL|PQ_BOOL,
    705                     0, &halt,  NULL);
    706     if (!parseEndOk(a, &pt, &rv)) {
    707         if (CMD_OK != rv) {
    708             return rv;
    709         }
    710     }
    711 
    712 
    713     if (halt) {
    714         /* Halt both uCs so that the dump is clean */
    715         READ_UC_0_RST_CONTROLr(unit, &reg0);
    716         regs = reg0;
    717         soc_reg_field_set(unit, UC_0_RST_CONTROLr, &regs, CPUHALT_Nf, 0);
    718         WRITE_UC_0_RST_CONTROLr(unit, regs);
    719             
    720         READ_UC_0_RST_CONTROLr(unit, &reg1);
    721         regs = reg0;
    722         soc_reg_field_set(unit, UC_0_RST_CONTROLr, &regs, CPUHALT_Nf, 0);
    723         WRITE_UC_1_RST_CONTROLr(unit, regs);
    724     }
    725         
    726 #ifdef NO_FILEIO
    727     cli_out("no filesystem\n");
    728 #else
    729 #ifndef NO_CTRL_C 
    730     if (!setjmp(ctrl_c)) {
    731         sh_push_ctrl_c(&ctrl_c);
    732 #endif
    733 
    734         fp = sal_fopen(filename, "w");
    735         if (!fp) {
    736             cli_out("%s: Error: Unable to open file: %s\n",
    737                     ARG_CMD(a), filename);
    738             rv = CMD_FAIL;
    739         } else {
    740             rv = mcs_dump(unit, fp, addr, mem_size);
    741             sal_fclose((FILE *)fp);
    742             fp = NULL;
    743         }
    744 #ifndef NO_CTRL_C 
    745     } else if (fp) {
    746         sal_fclose((FILE *)fp);
    747         fp = NULL;
    748         rv = CMD_INTR;
    749     }
    750 
    751     sh_pop_ctrl_c();
    752 #endif
    753 #endif /* NO_FILEIO */
    754 
    755     if (halt) {
    756         /* Put both uCs back in previous state */
    757         WRITE_UC_0_RST_CONTROLr(unit, reg0);
    758         WRITE_UC_1_RST_CONTROLr(unit, reg1);
    759     }
    760 
    761         
    762     return(rv);
    763 }
    764 
    765 char mcsmsg_usage[] =
    766     "Parameters: [ucnum|Start|Stop]\n\t"
    767     "Control messaging with the UCs.\n\t"
    768     "ucnum = ucnum to start comminicating with (must start first).\n\t"
    769     "Init = Init messaging with all uCs.\n\t"
    770     "Halt = Halt messaging with all uCs.\n\t"
    771     "Stop = Stop messaging with uC.\n";
    772 
    773 cmd_result_t
    774 mcsmsg_cmd(int unit, args_t *a)
    775 /*
    776  * Function: 	mcsmsg_cmd
    777  * Purpose:	Start messading with the MCS.
    778  * Parameters:	unit - unit
    779  *		a - args, 0, 1, stop.
    780  * Returns:	CMD_OK/CMD_FAIL/CMD_USAGE
    781  */
    782 {
    783     char *c;
    784     int ucnum;
    785 
    786     if (!sh_check_attached("mcsmsg", unit)) {
    787         return(CMD_FAIL);
    788     }
    789 
    790     if (!soc_feature(unit, soc_feature_uc)) {
    791         return (CMD_FAIL);
    792     } 
    793 
    794     if (ARG_CNT(a) < 1) {
    795         return(CMD_USAGE);
    796     }
    797 
    798     c = ARG_GET(a);
    799     if (isint(c)) {
    800         ucnum = parse_integer(c);
    801         if (ucnum < SOC_INFO(unit).num_ucs) {
    802             soc_cmic_uc_msg_uc_start(unit, ucnum);
    803         } else {
    804             cli_out("%s: Error: uC Num not legal\n", ARG_CMD(a));
    805             return(CMD_USAGE);
    806         }
    807         
    808     } else if (sal_strcasecmp(c, "INIT") == 0) {
    809         soc_cmic_uc_msg_start(unit);
    810         
    811     } else if (sal_strcasecmp(c, "HALT") == 0) {
    812         soc_cmic_uc_msg_shutdown_halt(unit);
    813         
    814     } else if (sal_strcasecmp(c, "STOP") == 0) {
    815         if (ARG_CNT(a) < 1) {
    816             return(CMD_USAGE);
    817         }
    818         c = ARG_GET(a);
    819         ucnum = parse_integer(c);
    820         if (ucnum < SOC_INFO(unit).num_ucs) {
    821             soc_cmic_uc_msg_uc_shutdown_halt(unit, ucnum);
    822         } else {
    823             cli_out("%s: Error: uC Num not legal\n", ARG_CMD(a));
    824             return(CMD_USAGE);
    825         }
    826     } else {
    827         cli_out("%s: Error: Invalid parameter\n", ARG_CMD(a));
    828         return(CMD_USAGE);
    829     } 
    830 
    831     return (CMD_OK);
    832 
    833 }
    834 
    835 char mcscmd_usage[] =
    836     "Parameters: <ucnum> <cmd>\n\t"
    837     "Execute cmd on uC\n\t"
    838     "ucnum = ucnum to start comminicating with (must start first).\n\t"
    839     "cmd = <stats reset>.\n";
    840 
    841 /*
    842  * Function: 	mcsmsg_cmd
    843  * Purpose:	Start messading with the MCS.
    844  * Parameters:	unit - unit
    845  *		a - args, 0, 1, stop.
    846  * Returns:	CMD_OK/CMD_FAIL/CMD_USAGE
    847  */
    848 cmd_result_t
    849 mcscmd_cmd(int unit, args_t *a)
    850 {
    851     char         *c;
    852     int           uC;
    853 
    854     if (!sh_check_attached("mcsmsg", unit)) {
    855         return CMD_FAIL;
    856     }
    857 
    858     if (!soc_feature(unit, soc_feature_uc)) {
    859         return CMD_FAIL;
    860     }
    861 
    862 
    863     if (ARG_CNT(a) < 1) {
    864         return CMD_USAGE;
    865     }
    866 
    867     c = ARG_GET(a);
    868     if (isint(c)) {
    869         uC = parse_integer(c);
    870         if (uC >= SOC_INFO(unit).num_ucs) {
    871             cli_out("%s: Error: uC Num not legal\n", ARG_CMD(a));
    872             return CMD_USAGE;
    873         }
    874     } else {
    875         cli_out("Error: uC Num not specified\n");
    876         return CMD_USAGE;
    877     }
    878 
    879     if (ARG_CNT(a) == 2) {
    880         c = ARG_GET(a);
    881         if (sal_strcasecmp(c, "STATS") == 0) {
    882             c = ARG_GET(a);
    883             if (sal_strcasecmp(c, "RESET") == 0) {
    884                 if (soc_uc_stats_reset(unit, uC) != SOC_E_NONE) {
    885                     cli_out("Error: stats reset cmd fail\n");
    886                 }
    887                 return CMD_OK;
    888             }
    889         } else if (sal_strcasecmp(c, "CONSOLE") == 0) {
    890             c = ARG_GET(a);
    891             if (sal_strcasecmp(c, "ON") == 0) {
    892                 if (soc_uc_console_log(unit, uC, 1) != SOC_E_NONE) {
    893                     cli_out("Error: console log ON cmd fail\n");
    894                 }
    895                 return CMD_OK;
    896             } else if(sal_strcasecmp(c, "OFF") == 0) {
    897                 if (soc_uc_console_log(unit, uC, 0) != SOC_E_NONE) {
    898                     cli_out("Error: console log OFF cmd fail\n");
    899                 }
    900                 return CMD_OK;
    901             }
    902         }
    903     }
    904 
    905     /* Only stats reset supported for now */
    906     return CMD_USAGE;
    907 }
    908 
    909 void mcs_core_status(int unit, int uC, uint32 base)
    910 {
    911     int i;
    912     uint32 cpsr;
    913     char *version;
    914     uint16 dev_id;
    915     uint8 rev_id;
    916     uint32  regVal;
    917 
    918     soc_cm_get_id(unit, &dev_id, &rev_id);
    919 
    920     /* Skip getting status of Firmware for Core-1 in Dagger2 */
    921     if ((dev_id == BCM56233_DEVICE_ID) && (uC == 1)) {
    922         return;
    923     }
    924 
    925     /* CPSR is at offset 0x60 from start of TCM */
    926     /* Core 0's TCM is at a PCI address of 0x100000, Core 1's is at 0x200000 */
    927     cpsr = soc_uc_mem_read(unit, base + 0x60);
    928     cli_out("uC %d status: %s\n", uC, (cpsr) ? "Fault" : "Ok");
    929     if (uC < MAX_UCS)
    930         sal_memcpy(fwInfo[uC].status,
    931                    (cpsr) ? "Fault" : "Ok",
    932                    (cpsr) ? sizeof("Fault") : sizeof("Ok"));
    933     if (cpsr) {
    934         regVal = soc_uc_mem_read(unit, base + 0x64);
    935         cli_out("\tcpsr\t0x%08x\n", cpsr);
    936         cli_out("\ttype\t0x%08x\n", regVal);
    937         if (uC < MAX_UCS) {
    938             fwInfo[uC].cpsr = cpsr;
    939             fwInfo[uC].type = regVal;
    940         }
    941 
    942         for (i = 0; i < 16; ++i) {
    943             regVal = soc_uc_mem_read(unit, base + 0x20 + i*4);
    944             cli_out("\tr%d\t0x%08x\n",
    945                     i, regVal);
    946             if (uC < MAX_UCS)
    947                 fwInfo[uC].armReg[i] = regVal;
    948         }
    949     }
    950     else {
    951         version = soc_uc_firmware_version(unit, uC);
    952         if (version) {
    953             cli_out("version: %s\n", version);
    954             if (uC < MAX_UCS)
    955                 sal_memcpy(fwInfo[uC].fw_version, version, 100);
    956             soc_cm_sfree(unit, version);
    957         }
    958     }
    959 }
    960 
    961 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_GDPLL)
    962 extern int _bcm_esw_gdpll_m7_status (int unit, uint8 *pBuff);
    963 #endif
    964 
    965 char mcsstatus_usage[] =
    966     "Prints fault status of microcontrollers\n\t\t"
    967 #ifndef COMPILER_STRING_CONST_LIMIT    
    968     "Parameters: [Quick=true|false] [TimeOutUs=<val>]\n\t\t"
    969     "Quick = Call Ping function instead of FW Ver.(false)\n\t\t"
    970     "TimeOutUs = Ping Timeout in uSecs. Used only in Quick mode. (1Sec)\n"
    971 #endif
    972     ;
    973 
    974 cmd_result_t
    975 mcsstatus_cmd(int unit, args_t *a)
    976 /*
    977  * Function: mcsstatus_cmd
    978  * Purpose: Show fault status of MCS
    979  * Parameters: unit - unit
    980  *      a - args (none)
    981  * Returns: CMD_OK/CMD_FAIL/CMD_USAGE
    982  */
    983 {
    984     int quick = 0, uc_num = 0, rv = 0, to = 0;
    985     parse_table_t  pt;
    986     char         *c;
    987 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_GDPLL)
    988     uint8 *version = NULL;
    989     uint8 buffer[20/*DPLL_FW_VERSION_SIZE*/];
    990 #endif
    991 
    992     if (!sh_check_attached("mcsmsg", unit)) {
    993         return(CMD_FAIL);
    994     }
    995 
    996     if (!soc_feature(unit, soc_feature_uc)) {
    997         return (CMD_FAIL);
    998     }
    999 
   1000     if (ARG_CNT(a) > 0) {
   1001         /* Just peek into the argument without consuming it
   1002          * In case it is not an integer, it is needed for the parse table.
   1003          */
   1004         c = ARG_CUR(a);
   1005         if (isint(c)) {
   1006             uint32 addr = parse_integer(c);
   1007             cli_out("%08x: %08x\n", addr, soc_uc_mem_read(unit, addr));
   1008             ARG_DISCARD(a);
   1009             return(CMD_OK);
   1010         }
   1011 
   1012         parse_table_init(unit, &pt);
   1013         parse_table_add(&pt, "Quick", PQ_DFL|PQ_BOOL,
   1014                         0, &quick,  NULL);
   1015         parse_table_add(&pt, "TimeOutUs", PQ_DFL|PQ_INT,
   1016                         (void *)(1*1000*1000), &to, NULL);
   1017         if (!parseEndOk(a, &pt, &rv)) {
   1018             if (CMD_OK != rv) {
   1019                 return rv;
   1020             }
   1021         }
   1022     }
   1023 
   1024     if (quick) {
   1025         /* Just Ping */
   1026         for(uc_num = 0; uc_num < SOC_INFO(unit).num_ucs; uc_num++) {
   1027             rv = soc_uc_ping(unit, uc_num, (sal_usecs_t)to);
   1028             cli_out("uC %d status: ", uc_num);
   1029             switch(rv) {
   1030             case SOC_E_UNAVAIL:
   1031                 cli_out("No uC / MCS support\n");
   1032                 break;
   1033             case SOC_E_PARAM:
   1034                 cli_out("uC Invalid for this chip\n");
   1035                 break;
   1036             case SOC_E_DISABLED:
   1037                 cli_out("ARM core is in reset\n");
   1038                 break;
   1039             case SOC_E_INIT:
   1040                 cli_out("uKernel messaging is not initialized\n");
   1041                 break;
   1042             case SOC_E_TIMEOUT:
   1043                 cli_out("uKernel not responding\n");
   1044                 break;
   1045             case SOC_E_NONE:
   1046                 cli_out("OK\n");
   1047                 break;
   1048             default:
   1049                 cli_out("Unknown Error\n");
   1050                 break;
   1051             }
   1052         }
   1053         return CMD_OK;
   1054     }
   1055 
   1056     for(uc_num=0; uc_num < MAX_UCS; uc_num++) {
   1057         if (uc_num < SOC_INFO(unit).num_ucs) {
   1058             fwInfo[uc_num].status[0] = '\0';
   1059             fwInfo[uc_num].fw_version[0] = '\0';
   1060         }
   1061     }
   1062 
   1063     /* If a fault happens, the register dump will include a non-zero CPSR */
   1064 
   1065     if (soc_feature(unit, soc_feature_iproc)) {
   1066     
   1067 #if defined(BCM_UC_MHOST_SUPPORT)
   1068         if (soc_feature(unit, soc_feature_uc_mhost)) {
   1069         
   1070             int uc, addr;
   1071             
   1072             /* iProc mHost: vectors and exception registers are in ATCM */
   1073             for(uc=0; uc<SOC_INFO(unit).num_ucs; uc++) {
   1074 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_GDPLL)
   1075                 version = &buffer[0];
   1076                 if ((SOC_IS_MONTEREY(unit) && (uc == 2))) {
   1077                     rv = _bcm_esw_gdpll_m7_status(unit, buffer);
   1078                     if (rv == BCM_E_NONE) {
   1079                         version = &buffer[0];
   1080                         cli_out("uC 2 status: Ok\n");
   1081                         cli_out("version: %.6s %.5s %s\n", version, version+6, version+11);
   1082                     } else {
   1083                         cli_out("uC 2 status: RESET\n");
   1084                     }
   1085                     continue;
   1086                 }
   1087 #endif
   1088                 if (soc_uc_in_reset(unit, uc)) {
   1089                     cli_out("uC %d status: RESET\n", uc);
   1090                     if (uc < MAX_UCS)
   1091                         sal_memcpy(fwInfo[uc].status, "RESET", sizeof("RESET"));
   1092                 } else {
   1093                     addr = 0x01000000 + 0x00100000 * uc;
   1094 #ifdef BCM_SABER2_SUPPORT
   1095                     if (SOC_IS_SABER2(unit)) {
   1096                         if (uc == 2) {
   1097                             addr = 0x01160000;
   1098                         }
   1099                     }
   1100 #endif
   1101 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
   1102                     if (SOC_IS_TRIDENT3(unit) || SOC_IS_TOMAHAWK2(unit) || SOC_IS_TOMAHAWK3(unit) || SOC_IS_MAVERICK2(unit)) {
   1103                         addr = 0x01100000 + 0x00060000 * uc;
   1104                     }
   1105 #endif
   1106 #if defined(BCM_JERICHO_2_SUPPORT)
   1107                     if (SOC_IS_JERICHO_2_ONLY(unit)) {
   1108                         addr = 0x01100000 + 0x00060000 * uc;
   1109                     }
   1110 #endif
   1111 #ifdef BCM_APACHE_SUPPORT
   1112                     if (SOC_IS_APACHE(unit)) {
   1113                         addr = 0x01100000 + 0x00060000 * uc;
   1114                     }
   1115 #endif
   1116                     mcs_core_status(unit, uc, addr);
   1117                 }
   1118             }
   1119 
   1120             return CMD_OK;
   1121         }
   1122 #endif
   1123 
   1124         /* iProc - L2Cache + SRAM for now. */
   1125         if (soc_uc_in_reset(unit, 0)) {
   1126             cli_out("uC 0 status: RESET\n");
   1127             sal_memcpy(fwInfo[0].status, "RESET", sizeof("RESET"));
   1128         } else {
   1129 #if defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
   1130             if (SOC_IS_HURRICANE2(unit) || SOC_IS_HURRICANE3(unit)) {
   1131                 mcs_core_status(unit, 0, 0x00004000);
   1132             } else
   1133 #endif /* BCM_HURRICANE2_SUPPORT || BCM_HURRICANE3_SUPPORT */
   1134 
   1135             mcs_core_status(unit, 0, 0x1b004000);
   1136         }
   1137         if (SOC_INFO(unit).num_ucs > 1) {
   1138             if (soc_uc_in_reset(unit, 1)) {
   1139                 cli_out("uC 1 status: RESET\n");
   1140                 sal_memcpy(fwInfo[1].status, "RESET", sizeof("RESET"));
   1141             }
   1142             else {
   1143                 mcs_core_status(unit, 1, 0x1b034000);
   1144             }
   1145         }
   1146     }
   1147     else {
   1148         /* CMICm with TCMs */
   1149         if (soc_uc_in_reset(unit, 0)) {
   1150             cli_out("uC 0 status: RESET\n");
   1151             sal_memcpy(fwInfo[0].status, "RESET", sizeof("RESET"));
   1152         }
   1153         else {           
   1154             mcs_core_status(unit, 0, 0x100000);
   1155         }
   1156         if (soc_uc_in_reset(unit, 1)) {
   1157             cli_out("uC 1 status: RESET\n");
   1158             sal_memcpy(fwInfo[1].status, "RESET", sizeof("RESET"));
   1159         }
   1160         else {           
   1161             mcs_core_status(unit, 1, 0x200000);
   1162         }
   1163     }
   1164 
   1165     return CMD_OK;
   1166 }
   1167 
   1168 
   1169 char mcstimestamp_usage[] =
   1170     "Parameters: [event_id] [ENable|DISable|CHanGe]\n\t"
   1171     "Display or configure timestamps captured by UC\n\t"
   1172     "event_id = timestamp event index.  If empty, all will print.\n\t"
   1173     "ENable = enable the specified timestamp event\n\t"
   1174     "DISable = disable specified timestamp event, unless used by firmware\n\t"
   1175     "CHanGe = poll specified timestamp event for a change before displaying\n";
   1176 
   1177 cmd_result_t
   1178 mcstimestamp_cmd(int unit, args_t *a)
   1179 {
   1180     char uint64_decimal_string[27];
   1181     int rv, i;
   1182     int min_event_id = 0;
   1183     int max_event_id = (soc_feature(unit, soc_feature_iproc)) ? (MOS_MSG_MAX_TS_EVENTS-1)/*18*/ : 12;
   1184 
   1185     char *arg = ARG_GET(a);
   1186     uint64 diff;
   1187     int poll_for_change = 0;
   1188 
   1189     if (!sh_check_attached("mcsmsg", unit)) {
   1190         return(CMD_FAIL);
   1191     }
   1192 
   1193     if (!soc_feature(unit, soc_feature_uc)) {
   1194         return (CMD_FAIL);
   1195     }
   1196 
   1197     if (arg) {
   1198         int event_id;
   1199 
   1200         if (!isint(arg)) {
   1201             return CMD_USAGE;
   1202         }
   1203         event_id = parse_integer(arg);
   1204 
   1205         arg = ARG_GET(a);
   1206         if (arg) {
   1207             if (parse_cmp("ENable", arg, 0)) {
   1208                 if (SOC_FAILURE(soc_cmic_uc_msg_timestamp_enable(unit, event_id))) {
   1209                     return CMD_FAIL;
   1210                 } else {
   1211                     return CMD_OK;
   1212                 }
   1213             }
   1214             if (parse_cmp("DISable", arg, 0)) {
   1215                 if (SOC_FAILURE(soc_cmic_uc_msg_timestamp_disable(unit, event_id))) {
   1216                     return CMD_FAIL;
   1217                 } else {
   1218                     return CMD_OK;
   1219                 }
   1220             }
   1221             if (parse_cmp("CHanGe", arg, 0)) {
   1222                 poll_for_change = 1;
   1223             } else {
   1224                 return CMD_USAGE;
   1225             }
   1226         }
   1227 
   1228         /* only a single integer argument */
   1229         min_event_id = event_id;
   1230         max_event_id = event_id;
   1231     }
   1232 
   1233     cli_out(" #  Last Timestamp    Prev Timestamp    <difference>  Equivalent TS1     Equivalent Full Time\n");
   1234 
   1235     for (i = min_event_id; i <= max_event_id; ++i) {
   1236         soc_cmic_uc_ts_data_t ts_data;
   1237 
   1238         rv = soc_cmic_uc_msg_timestamp_get(unit, i, &ts_data);
   1239         if (poll_for_change) {
   1240             soc_cmic_uc_ts_data_t ts_data_orig = ts_data;
   1241             int iter = 0;
   1242             const int max_iter = 100000;
   1243             while (rv == SOC_E_NONE && COMPILER_64_EQ(ts_data.hwts,ts_data_orig.hwts) && ++iter < max_iter) {
   1244                 rv = soc_cmic_uc_msg_timestamp_get(unit, i, &ts_data);
   1245             }
   1246             if (iter == max_iter) {
   1247                 cli_out("Timed out waiting for change in timestamp\n");
   1248             }
   1249         }
   1250         if (SOC_FAILURE(rv)) {
   1251             cli_out("soc_cmic_uc_msg_timestamp_get failed: %s (%d)\n", soc_errmsg(rv), rv);
   1252         } else {
   1253             diff = ts_data.hwts;
   1254             COMPILER_64_SUB_64(diff, ts_data.prev_hwts);
   1255 
   1256             format_uint64_decimal(uint64_decimal_string, ts_data.time.seconds, 0);
   1257 
   1258             cli_out("%2d: %08x:%08x %08x:%08x <%10u>  %08x:%08x  %s.%09u\n",
   1259                     i,
   1260                     (unsigned)COMPILER_64_HI(ts_data.hwts), (unsigned)COMPILER_64_LO(ts_data.hwts),
   1261                     (unsigned)COMPILER_64_HI(ts_data.prev_hwts), (unsigned)COMPILER_64_LO(ts_data.prev_hwts),
   1262                     (unsigned)COMPILER_64_LO(diff),
   1263                     (unsigned)COMPILER_64_HI(ts_data.hwts_ts1), (unsigned)COMPILER_64_LO(ts_data.hwts_ts1),
   1264                     uint64_decimal_string, (unsigned)ts_data.time.nanoseconds);
   1265         }
   1266     }
   1267 
   1268     return CMD_OK;
   1269 }
   1270 
   1271 
   1272 #endif /* CMICM support */