m0.c (8766B)
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: m0.c 8 * Purpose: ARM Cortex-M0 subsystem quad (M0SSQ) 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/drv.h> 17 #include <appl/diag/shell.h> 18 #include <appl/diag/system.h> 19 20 #if defined(BCM_CMICX_SUPPORT) 21 #include <soc/iproc.h> 22 #include <shared/cmicfw/cmicx_link.h> 23 #include <shared/cmicfw/iproc_fwconfig.h> 24 25 #define M0FW_FILENAME_SIZE (256) 26 #define _SOC_M0FW_DEFAULT_PATHS_NUM (7) 27 28 #ifndef NO_FILEIO 29 STATIC int 30 _soc_m0fw_default_filename(int unit, char *filename) { 31 int rv = SOC_E_NONE; 32 int i = 0, found = 0; 33 FILE *fp = NULL; 34 char filepath[M0FW_FILENAME_SIZE] = {0}; 35 36 /* Search for M0 FW binary file in these locations */ 37 char paths[_SOC_M0FW_DEFAULT_PATHS_NUM][80] = \ 38 {"../../rc/cmicfw/", "../rc/cmicfw", "rc/cmicfw/", "cmicfw/", 39 "../../../rc/cmicfw/","../../../../rc/cmicfw/", ""}; 40 41 if (sal_strlen(filename) > M0FW_FILENAME_SIZE) { 42 cli_out("Filename cannot be longer than %d\n", M0FW_FILENAME_SIZE); 43 return SOC_E_PARAM; 44 } 45 46 for(i = 0; i < _SOC_M0FW_DEFAULT_PATHS_NUM; i++) { 47 sal_strncpy(filepath, paths[i], M0FW_FILENAME_SIZE-1); 48 /* M0 FW binary filename is fixed */ 49 sal_strncat(filepath, filename, sal_strlen(filename)); 50 fp = sal_fopen(filepath, "rb"); 51 if (fp) { 52 found = 1; 53 strncpy(filename, filepath, M0FW_FILENAME_SIZE-1); 54 sal_fclose(fp); 55 break; 56 } 57 } 58 59 if (!found) { 60 rv = SOC_E_EXISTS; 61 } 62 63 return rv; 64 } 65 #endif /* NO_FILEIO */ 66 67 68 char m0_usage[] = 69 "Parameters: <command> [<ucore>] [<address>] [<file>]\n" 70 #ifndef COMPILER_STRING_CONST_LIMIT 71 "\tcommand = [load/status/stats]\n" 72 "\tucore = Cortex-M0 ucore number to be loaded.\n" 73 "\taddress = offset of shared SRAM to load binary file\n" 74 "\tfile = binary file name\n" 75 #endif 76 ; 77 78 cmd_result_t 79 m0_cmd(int unit, args_t *a) 80 /* 81 * Function: m0_cmd 82 * Purpose: Load a file into M0SSQ Cortex-M0 Private TCM 83 * Parameters: unit - unit 84 * a - args, each of the files to be displayed. 85 * Returns: CMD_OK/CMD_FAIL/CMD_USAGE 86 */ 87 { 88 cmd_result_t rv = CMD_OK; 89 char *c; 90 int ucnum; 91 soc_stat_t *stat; 92 #if defined (BCM_ESW_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 93 soc_ls_heartbeat_t ls_hbeat; 94 #endif /* BCM_ESW_SUPPORT || BCM_DNXF_SUPPORT */ 95 #ifndef NO_FILEIO 96 int err; 97 uint32 buf[64], addr; 98 int fsize = 0, reqsize = 0, size = 0, i; 99 int buf_size = sizeof(buf); 100 int big_pio, big_packet, big_other; 101 char filename[M0FW_FILENAME_SIZE] = {0}; 102 #endif 103 104 #ifndef NO_FILEIO 105 #ifndef NO_CTRL_C 106 jmp_buf ctrl_c; 107 #endif 108 FILE * volatile fp = NULL; 109 #endif 110 111 /* check for simulation*/ 112 if (SAL_BOOT_BCMSIM) { 113 return(rv); 114 } 115 116 if (!soc_feature(unit, soc_feature_cmicx)) { 117 return (CMD_FAIL); 118 } 119 120 if (!sh_check_attached("m0", unit)) { 121 return(CMD_FAIL); 122 } 123 124 if (!ARG_CNT(a)) { 125 return(CMD_USAGE); 126 } 127 128 stat = SOC_STAT(unit); 129 c = ARG_GET(a); 130 131 if (!sal_strcasecmp(c, "load")) { 132 c = ARG_GET(a); 133 if (!isint(c)) { 134 cli_out("%s: Error: uC Num not specified\n", ARG_CMD(a)); 135 return(CMD_USAGE); 136 } 137 138 ucnum = parse_integer(c); 139 if (ucnum < 0 || ucnum > 3 /* SOC_INFO(unit).num_ucs */) { 140 cli_out("Invalid uCnum number: %d, must be in the range 0 to 3", ucnum); 141 return(CMD_FAIL); 142 } 143 144 #ifndef NO_FILEIO 145 c = ARG_GET(a); 146 if (!isint(c)) { 147 cli_out("%s: Error: Address offset not specified\n", ARG_CMD(a)); 148 return(CMD_USAGE); 149 } 150 addr = parse_address(c); 151 #endif 152 153 c = ARG_GET(a); 154 155 if (c == NULL) { 156 cli_out("%s: Error: No file specified\n", ARG_CMD(a)); 157 return(CMD_USAGE); 158 } 159 160 #ifdef NO_FILEIO 161 cli_out("no filesystem\n"); 162 #else 163 if (sal_strlen(c) > M0FW_FILENAME_SIZE) { 164 cli_out("Filename cannot be longer than %d\n", M0FW_FILENAME_SIZE); 165 return(CMD_FAIL); 166 } 167 168 sal_strncpy(filename, c, sal_strlen(c)); 169 170 /* Check if file can be opened */ 171 fp = sal_fopen(filename, "rb"); 172 173 if (fp) { 174 sal_fclose((FILE *)fp); 175 fp = NULL; 176 } else { 177 /* Search for M0 FW binary file in default locations */ 178 err = _soc_m0fw_default_filename(unit, filename); 179 if (err != SOC_E_NONE) { 180 cli_out("%s: Error: M0 Firmware file not found!!\n", ARG_CMD(a)); 181 return (CMD_FAIL); 182 } 183 } 184 cli_out("Loading M0 Firmware located at %s\n", filename); 185 #endif /* NO_FILEIO */ 186 187 #ifdef NO_FILEIO 188 cli_out("no filesystem\n"); 189 #else 190 #ifndef NO_CTRL_C 191 if (!setjmp(ctrl_c)) { 192 sh_push_ctrl_c(&ctrl_c); 193 #endif 194 /* See if we can open the file before doing anything else */ 195 fp = sal_fopen(filename, "rb"); 196 if (!fp) { 197 cli_out("%s: Error: Unable to open file: %s\n", 198 ARG_CMD(a), filename); 199 rv = CMD_FAIL; 200 #ifndef NO_CTRL_C 201 sh_pop_ctrl_c(); 202 #endif 203 return rv; 204 } 205 206 addr += soc_iproc_percore_membase_get(unit, ucnum); 207 208 fsize = sal_fsize(fp); 209 210 if (fsize <= 0) { 211 cli_out("%s: Error: file size is not valid: size = %d\n", 212 ARG_CMD(a), fsize); 213 sal_fclose((FILE *)fp); 214 #ifndef NO_CTRL_C 215 sh_pop_ctrl_c(); 216 #endif 217 return CMD_FAIL; 218 } 219 soc_endian_get(unit, &big_pio, &big_packet, &big_other); 220 do { 221 reqsize = (fsize > buf_size) ? buf_size : fsize; 222 fsize -= reqsize; 223 size = sal_fread(buf, 1 , reqsize, fp); 224 if (size < reqsize) { 225 cli_out("%s: Error: file read failed : requested = %d, read = %d\n", 226 ARG_CMD(a), reqsize, size); 227 sal_fclose((FILE *)fp); 228 #ifndef NO_CTRL_C 229 sh_pop_ctrl_c(); 230 #endif 231 return CMD_FAIL; 232 } 233 234 for (i = 0; i < ((size + 3) / 4); i++) { 235 if (big_other) { 236 buf[i] = ((buf[i] & 0xff) << 24) | ((buf[i] & 0xff00) << 8) | ((buf[i] >> 8) & 0xff00) | ((buf[i] >> 24) & 0xff); 237 } else { 238 if (SOC_IS_DNX(unit) || SOC_IS_DNXF(unit) || SOC_IS_ESW(unit)) { 239 #ifndef LE_HOST 240 buf[i] = ((buf[i] & 0xff) << 24) | ((buf[i] & 0xff00) << 8) | ((buf[i] >> 8) & 0xff00) | ((buf[i] >> 24) & 0xff); 241 #endif 242 } 243 } 244 soc_cm_iproc_write(unit, addr, buf[i]); 245 addr += 4; 246 } 247 } while(fsize); 248 249 sal_fclose((FILE *)fp); 250 fp = NULL; 251 252 #ifndef NO_CTRL_C 253 } else if (fp) { 254 sal_fclose((FILE *)fp); 255 fp = NULL; 256 rv = CMD_INTR; 257 } 258 sh_pop_ctrl_c(); 259 #endif 260 #endif /* NO_FILEIO */ 261 sal_usleep(10000); 262 } else if (!sal_strcasecmp(c, "status")) { 263 #if defined (BCM_ESW_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 264 int st = 0; 265 st = soc_cmicx_linkscan_heartbeat(unit, &ls_hbeat); 266 cli_out("M0 FW is %s\n", ((st == SOC_E_NONE) ? "Running" : "NOT Running")); 267 cli_out("M0 FW Version is %d.%d\n", 268 (ls_hbeat.m0_fw_version >> 16), (ls_hbeat.m0_fw_version & 0xFFFF)); 269 cli_out("Host FW Version is %d.%d\n", 270 (ls_hbeat.host_fw_version >> 16), (ls_hbeat.host_fw_version & 0xFFFF)); 271 if (ls_hbeat.host_fw_version != ls_hbeat.m0_fw_version) { 272 cli_out("Host and M0 FW Versions do not match!!!\n"); 273 } 274 #endif /* BCM_ESW_SUPPORT || BCM_DNXF_SUPPORT */ 275 } else if (!sal_strcasecmp(c, "stats")) { 276 cli_out("M0: msg=%d resp=%d intr=%d\n", 277 stat->m0_msg, stat->m0_resp, 278 stat->m0_intr); 279 280 cli_out("Uc sw programmable total intr=%d\n", 281 stat->uc_sw_prg_intr); 282 283 cli_out("M0 sw programmable intr: u0=%d u1=%d u2=%d u3=%d\n", 284 stat->m0_u0_sw_intr, stat->m0_u1_sw_intr, 285 stat->m0_u2_sw_intr, stat->m0_u3_sw_intr); 286 } 287 288 return(rv); 289 } 290 #endif /* CMICX support */