cmicm.c (17070B)
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 * CMICm peripherals commands 8 */ 9 10 #include <assert.h> 11 #include <sal/core/libc.h> 12 #include <bcm/error.h> 13 #include <shared/bsl.h> 14 #include <soc/types.h> 15 #include <soc/mspi.h> 16 #include <soc/cmicm.h> 17 #include <shared/bsl.h> 18 #include <appl/diag/shell.h> 19 #include <appl/diag/system.h> 20 #include "appl/diag/diag.h" 21 22 #ifdef BCM_CMICM_SUPPORT 23 24 #define CMICM_MSPI_BLOCK_SIZE 16 25 26 27 char mspi_usage[] = 28 "Usage :\n\t" 29 "mspi [device = n] [CPHA=n][CPOL=n]\n\t" 30 "mspi [device = n] [CPHA=n][CPOL=n] load <hexfile>\n\t" 31 "mspi [device = n] [CPHA=n][CPOL=n] write <hexdata>\n\t" 32 "mspi [device = n] [CPHA=n][CPOL=n] read <numbytes>\n\t" 33 "mspi [device = n] [CPHA=n][CPOL=n] write <hexdata> read <numbytes>\n\t" 34 "Optionally select a device and configres. The device number is specific to chip/board.\n\t" 35 "<hexfile> is ASCII file, with hex bytes separated by white space\n"; 36 37 cmd_result_t 38 mspi_cmd(int unit, args_t *a) 39 { 40 volatile cmd_result_t rv = CMD_OK; 41 char *c , *filename; 42 int dev,cpol, cpha, offset_size = 0; 43 volatile int wbytes = 0, rbytes=0; 44 int start_byte, num_wbytes, num_rbytes; 45 uint8 wdata[256]; 46 uint8 rdata[256]; 47 parse_table_t pt; 48 #ifndef NO_FILEIO 49 char input[256]; 50 #ifndef NO_CTRL_C 51 jmp_buf ctrl_c; 52 #endif 53 FILE * volatile fp = NULL; 54 #endif 55 56 if (!sh_check_attached("mspi", unit)) { 57 return(CMD_FAIL); 58 } 59 60 if (!soc_feature(unit, soc_feature_cmicm)) { 61 return(CMD_FAIL); 62 } 63 64 if (ARG_CNT(a) == 0) { 65 return CMD_USAGE; 66 } 67 68 sal_memset(rdata, 0, sizeof (rdata)); 69 dev=-1; 70 cpol=-1; 71 cpha=-1; 72 73 parse_table_init(unit, &pt); 74 parse_table_add(&pt, "Device", PQ_DFL|PQ_INT, 75 (void *)( 0), &dev, NULL); 76 parse_table_add(&pt, "CPOL", PQ_DFL|PQ_INT, 77 (void *)( 0), &cpol, NULL); 78 parse_table_add(&pt, "CPHA", PQ_DFL|PQ_INT, 79 (void *)( 0), &cpha, NULL); 80 81 if (parse_arg_eq(a, &pt) < 0) { 82 cli_out("%s: Error: Unknown option: %s\n", ARG_CMD(a), ARG_CUR(a)); 83 parse_arg_eq_done(&pt); 84 return(CMD_FAIL); 85 } 86 parse_arg_eq_done(&pt); 87 88 if ((dev != -1) || (cpol != -1) || (cpha != -1)) { 89 if (soc_mspi_config(unit, dev, cpol, cpha) != SOC_E_NONE){ 90 cli_out("MSPI: Failure Configuring\n"); 91 return CMD_FAIL; 92 } 93 } 94 95 if (ARG_CNT(a) == 0) { 96 return CMD_OK; 97 } 98 99 c = ARG_GET(a); 100 101 if (!sal_strcasecmp(c, "load")) { 102 c = ARG_GET(a); 103 filename = c; 104 if (filename == NULL) { 105 cli_out("MSPI: %s: Error: No file specified\n", ARG_CMD(a)); 106 return(CMD_USAGE); 107 } 108 #ifdef NO_FILEIO 109 cli_out("no filesystem\n"); 110 rv = CMD_FAIL; 111 #else 112 #ifndef NO_CTRL_C 113 if (!setjmp(ctrl_c)) { 114 sh_push_ctrl_c(&ctrl_c); 115 #endif 116 fp = sal_fopen(filename, "r"); 117 if (!fp) { 118 cli_out("MSPI: %s: Error: Unable to open file: %s\n", 119 ARG_CMD(a), filename); 120 rv = CMD_FAIL; 121 } else { 122 while ((rv == CMD_OK) && (c = sal_fgets(input, sizeof(input) - 1, fp))) { 123 while (*c) { 124 if (isspace((unsigned)(*c))) { /* Skip whitespace */ 125 c++; 126 } else { 127 if (!isxdigit((unsigned)*c) || 128 !isxdigit((unsigned)*(c+1))) { 129 cli_out("MSPI: %s: Invalid character\n", ARG_CMD(a)); 130 rv = CMD_FAIL; 131 break; 132 } 133 offset_size = sizeof(wdata); 134 if (wbytes >= offset_size) { 135 cli_out("MSPI: %s: Data memory exceeded\n", ARG_CMD(a)); 136 rv = CMD_FAIL; 137 break; 138 } 139 wdata[wbytes++] = (xdigit2i(*c) << 4) | xdigit2i(*(c + 1)); 140 c += 2; 141 } 142 } 143 } 144 sal_fclose((FILE *)fp); 145 fp = NULL; 146 } 147 #ifndef NO_CTRL_C 148 } else if (fp) { 149 sal_fclose((FILE *)fp); 150 fp = NULL; 151 rv = CMD_INTR; 152 } 153 #endif 154 155 sh_pop_ctrl_c(); 156 #endif /* NO_FILEIO */ 157 158 if (rv != CMD_OK) { 159 return rv; 160 } 161 LOG_VERBOSE(BSL_LS_SOC_COMMON, 162 (BSL_META_U(unit, 163 "MSPI: Writing %d bytes from file %s\n"), wbytes, filename)); 164 for(start_byte=0; start_byte < wbytes; start_byte+=CMICM_MSPI_BLOCK_SIZE) { 165 num_wbytes = ((start_byte + CMICM_MSPI_BLOCK_SIZE) > wbytes) ? 166 (wbytes - start_byte) : CMICM_MSPI_BLOCK_SIZE; 167 if (soc_mspi_write8(unit, (uint8 *) &wdata[start_byte], num_wbytes) != SOC_E_NONE) { 168 cli_out("MSPI: Write Fail\n"); 169 return CMD_FAIL; 170 } 171 } 172 return rv; 173 } 174 175 if (sal_strcasecmp(c, "write") && 176 sal_strcasecmp(c, "read")) { 177 cli_out("Neither Write Nor Read\n"); 178 return CMD_USAGE; 179 } 180 181 if (!sal_strcasecmp(c, "write")) { 182 while ((c = ARG_GET(a)) != NULL) { 183 if (!sal_strcasecmp(c, "read")) { 184 break; 185 } 186 while (*c) { 187 if (isspace((int)(*c))) { 188 c++; 189 } else { 190 if (!isxdigit((unsigned)*c) || 191 !isxdigit((unsigned)*(c+1))) { 192 cli_out("MSPI: %s: Invalid character\n", ARG_CMD(a)); 193 return(CMD_FAIL); 194 } 195 offset_size = sizeof(wdata); 196 if (wbytes >= offset_size) { 197 cli_out("MSPI: %s: Data memory exceeded\n", ARG_CMD(a)); 198 return(CMD_FAIL); 199 } 200 wdata[wbytes++] = (xdigit2i(*c) << 4) | xdigit2i(*(c + 1)); 201 c += 2; 202 } 203 } 204 } 205 } 206 207 if (c != NULL) { 208 if (!sal_strcasecmp(c, "read")) { 209 if (ARG_CNT(a) == 0) { 210 return CMD_USAGE; 211 } 212 c = ARG_GET(a); 213 if (!isint(c)) { 214 return CMD_USAGE; 215 } 216 rbytes = parse_integer(c); 217 } 218 } 219 220 if ((wbytes > 0) && (rbytes > 0)) { /* Write and read */ 221 if ((wbytes + rbytes) > CMICM_MSPI_BLOCK_SIZE) { 222 cli_out("MSPI: Too many bytes for single Write-read operation\n"); 223 return(CMD_FAIL); 224 } 225 LOG_VERBOSE(BSL_LS_SOC_COMMON, 226 (BSL_META_U(unit, 227 "MSPI: Writing %d bytes and Reading %d bytes\n"), 228 wbytes, rbytes)); 229 if (soc_mspi_writeread8(unit, (uint8 *) &wdata[0], wbytes,(uint8 *) &rdata[0], rbytes) != SOC_E_NONE) { 230 cli_out("MSPI: Write-Read Fail\n"); 231 return CMD_FAIL; 232 } 233 } else if (wbytes > 0){ /* Write Only */ 234 LOG_VERBOSE(BSL_LS_SOC_COMMON, 235 (BSL_META_U(unit, 236 "MSPI: Writing %d bytes\n"), wbytes)); 237 for(start_byte=0; start_byte < wbytes; start_byte+=CMICM_MSPI_BLOCK_SIZE) { 238 num_wbytes = ((start_byte + CMICM_MSPI_BLOCK_SIZE) > wbytes) ? 239 (wbytes - start_byte) : CMICM_MSPI_BLOCK_SIZE; 240 if (soc_mspi_write8(unit, (uint8 *) &wdata[start_byte], num_wbytes) != SOC_E_NONE) { 241 cli_out("MSPI: Write Fail\n"); 242 return CMD_FAIL; 243 } 244 } 245 } else if (rbytes > 0){ /* Read Only */ 246 LOG_VERBOSE(BSL_LS_SOC_COMMON, 247 (BSL_META_U(unit, 248 "MSPI: Reading %d bytes\n"), rbytes)); 249 for(start_byte=0; start_byte < rbytes; start_byte+=CMICM_MSPI_BLOCK_SIZE) { 250 num_rbytes = ((start_byte + CMICM_MSPI_BLOCK_SIZE) > rbytes) ? 251 (rbytes - start_byte) : CMICM_MSPI_BLOCK_SIZE; 252 if (soc_mspi_read8(unit, (uint8 *) &rdata[start_byte], num_rbytes) != SOC_E_NONE) { 253 cli_out("MSPI: Read Fail\n"); 254 return CMD_FAIL; 255 } 256 } 257 } else { 258 return CMD_USAGE; 259 } 260 261 if (rbytes > 0) { 262 /* Dump It */ 263 for(start_byte=0; start_byte < rbytes; start_byte++) { 264 cli_out("%02x ", rdata[start_byte]); 265 if ((start_byte % 8) == 7) { 266 cli_out("\n"); 267 } 268 } 269 cli_out("\n"); 270 } 271 272 return rv; 273 } 274 275 char dpll_usage[] = 276 "dpll [Config = n] [<Options>] write <addr> <data>\n\t" 277 "dpll [Config = n] [<Options>] read <addr>\n\t" 278 "\"Config\" overrides all the options with preset values\n" 279 #ifndef COMPILER_STRING_CONST_LIMIT 280 "\tTakes default <options> from \"dpll_params\" config variable if present\n" 281 "\tOptions are the following, separated by space:\n\t" 282 " DevSel=n : Override Mux for DPLL Selection\n\t" 283 " CPOL=0/1 : Clock Polarity\n\t" 284 " CPHA=0/1 : Clock Phase\n\t" 285 " AddrBitOrder=0/1 : 0 = MSB..LSB, 1 = LSB..MSB\n\t" 286 " DataBitOrder=0/1 : 0 = MSB..LSB, 1 = LSB..MSB\n\t" 287 " AddrWidth=1/2 : No of Bytes used for Addr\n\t" 288 " UseBrstBit-0/1 : Reserve Bit-0 of Addr as Burst Bit\n\t" 289 " UseRwBit=0/1 : Use MSBit (Bit-15 / Bit-7) of Addr as R/W' Bit\n" 290 #endif 291 ; 292 293 cmd_result_t 294 dpll_cmd(int unit, args_t *a) 295 { 296 volatile cmd_result_t rv = CMD_OK; 297 char *c; 298 uint32 addr, data, temp; 299 int rd_op, i; 300 int cfg=0, mux_sel = MSPI_DPLL; 301 int cpol=-1, cpha=-1, addr_bit_order=0, data_bit_order=0; 302 int addr_width=2, use_brst_bit=0, use_rw_bit=0; 303 volatile int wbytes = 2, rbytes=1; 304 uint8 wdata[16]; 305 uint8 rdata[16]; 306 int params[8]; 307 parse_table_t pt; 308 309 int preset_configs[3][8] = { 310 /* mux_sel,cpol,cpha,addr_bit_order,data_bit_order,addr_width,use_brst_bit,use_rw_bit */ 311 {2,0,1,0,0,2,1,1}, /* Maxim DPLL */ 312 {3,1,1,1,1,1,0,1}, /* IDT DPLL */ 313 {0,0,0,0,0,2,1,1} 314 }; 315 316 if (!sh_check_attached("dpll", unit)) { 317 return(CMD_FAIL); 318 } 319 320 if (!soc_feature(unit, soc_feature_cmicm)) { 321 return(CMD_FAIL); 322 } 323 324 if (ARG_CNT(a) == 0) { 325 return CMD_USAGE; 326 } 327 328 if (soc_property_get_csv(unit, spn_DPLL_PARAMS,8,params) == 8) { 329 mux_sel = params[0]; 330 cpol = params[1]; 331 cpha = params[2]; 332 addr_bit_order = params[3]; 333 data_bit_order = params[4]; 334 addr_width = params[5]; 335 use_brst_bit = params[6]; 336 use_rw_bit = params[7]; 337 } 338 339 sal_memset(rdata, 0, sizeof (rdata)); 340 341 parse_table_init(unit, &pt); 342 parse_table_add(&pt, "Config", PQ_DFL|PQ_INT, 343 INT_TO_PTR( 0), &cfg, NULL); 344 parse_table_add(&pt, "DevSel", PQ_DFL|PQ_INT, 345 INT_TO_PTR(mux_sel), &mux_sel, NULL); 346 parse_table_add(&pt, "CPOL", PQ_DFL|PQ_BOOL, 347 INT_TO_PTR(cpol), &cpol, NULL); 348 parse_table_add(&pt, "CPHA", PQ_DFL|PQ_BOOL, 349 INT_TO_PTR(cpha), &cpha, NULL); 350 parse_table_add(&pt, "AddrBitOrder", PQ_DFL|PQ_BOOL, 351 INT_TO_PTR(addr_bit_order), &addr_bit_order, NULL); 352 parse_table_add(&pt, "DataBitOrder", PQ_DFL|PQ_BOOL, 353 INT_TO_PTR(data_bit_order), &data_bit_order, NULL); 354 parse_table_add(&pt, "AddrWidth", PQ_DFL|PQ_INT, 355 INT_TO_PTR(addr_width), &addr_width, NULL); 356 parse_table_add(&pt, "UseBrstBit", PQ_DFL|PQ_BOOL, 357 INT_TO_PTR(use_brst_bit), &use_brst_bit, NULL); 358 parse_table_add(&pt, "UseRwBit", PQ_DFL|PQ_BOOL, 359 INT_TO_PTR(use_rw_bit), &use_rw_bit, NULL); 360 361 if (parse_arg_eq(a, &pt) < 0) { 362 cli_out("%s: Error: Unknown option: %s\n", ARG_CMD(a), ARG_CUR(a)); 363 parse_arg_eq_done(&pt); 364 return(CMD_FAIL); 365 } 366 parse_arg_eq_done(&pt); 367 368 if (cfg > 0) { 369 LOG_VERBOSE(BSL_LS_SOC_COMMON, 370 (BSL_META_U(unit, 371 "Using Preset %d\n"), cfg)); 372 mux_sel = preset_configs[cfg-1][0]; 373 cpol = preset_configs[cfg-1][1]; 374 cpha = preset_configs[cfg-1][2]; 375 addr_bit_order = preset_configs[cfg-1][3]; 376 data_bit_order = preset_configs[cfg-1][4]; 377 addr_width = preset_configs[cfg-1][5]; 378 use_brst_bit = preset_configs[cfg-1][6]; 379 use_rw_bit = preset_configs[cfg-1][7]; 380 } 381 382 if (soc_mspi_config(unit, mux_sel, cpol, cpha) != SOC_E_NONE){ 383 cli_out("MSPI: Failure Configuring\n"); 384 return CMD_FAIL; 385 } 386 387 if (ARG_CNT(a) == 0) { 388 return CMD_OK; 389 } 390 391 c = ARG_GET(a); 392 393 if (!sal_strcasecmp(c, "write")) { 394 rd_op = 0; 395 LOG_VERBOSE(BSL_LS_SOC_COMMON, 396 (BSL_META_U(unit, 397 "Write DPLL\n"))); 398 } else if (!sal_strcasecmp(c, "read")) { 399 rd_op = 1; 400 LOG_VERBOSE(BSL_LS_SOC_COMMON, 401 (BSL_META_U(unit, 402 "Read DPLL\n"))); 403 } else { 404 return CMD_USAGE; 405 } 406 407 if (ARG_CNT(a) == 0) { 408 return CMD_USAGE; 409 } 410 c = ARG_GET(a); 411 if (!isint(c)) { 412 return CMD_USAGE; 413 } 414 addr = parse_integer(c); 415 416 if(addr_width == 1) { 417 if (addr_bit_order) { 418 temp = 0; 419 for(i=0; i<8; i++) { 420 if (addr & (1<<i)) { 421 temp |= (1<<(7-i)); 422 } 423 } 424 temp = (temp >> use_rw_bit); 425 temp &= ((use_brst_bit) ? 0xfe : 0xff); 426 } else { 427 temp = addr; 428 temp = (temp << use_brst_bit); 429 temp &= ((use_rw_bit) ? 0x7f : 0xff); 430 } 431 if (use_rw_bit && rd_op) { 432 temp |= 0x80; 433 } 434 wdata[0] = temp & 0xff; 435 wbytes = 1; 436 } else if (addr_width == 2) { 437 if (addr_bit_order) { 438 temp = 0; 439 for(i=0; i<16; i++) { 440 if (addr & (1<<i)) { 441 temp |= (1<<(15-i)); 442 } 443 } 444 temp = (temp >> use_rw_bit); 445 temp &= ((use_brst_bit) ? 0xfffe : 0xffff); 446 } else { 447 temp = addr; 448 temp = (temp << use_brst_bit); 449 temp &= ((use_rw_bit) ? 0x7fff : 0xffff); 450 } 451 if (use_rw_bit && rd_op) { 452 temp |= 0x8000; 453 } 454 wdata[0] = (temp >> 8) & 0xff; 455 wdata[1] = temp & 0xff; 456 wbytes = 2; 457 } else { 458 cli_out("Only 1 or 2 byte addresses supported\n"); 459 return CMD_FAIL; 460 } 461 462 if(rd_op == 0) { /* Write */ 463 if (ARG_CNT(a) == 0) { 464 return CMD_USAGE; 465 } 466 c = ARG_GET(a); 467 if (!isint(c)) { 468 return CMD_USAGE; 469 } 470 data = parse_integer(c); 471 if (data_bit_order) { 472 temp = 0; 473 for(i=0; i<8; i++) { 474 if (data & (1<<i)) { 475 temp |= (1<<(7-i)); 476 } 477 } 478 data = temp; 479 } 480 wdata[wbytes] = (data & 0xff); 481 wbytes += 1; 482 rbytes = 0; 483 LOG_VERBOSE(BSL_LS_SOC_COMMON, 484 (BSL_META_U(unit, 485 "MSPI: Writing %d bytes\n"), wbytes)); 486 if (soc_mspi_write8(unit, (uint8 *) &wdata[0], wbytes) != SOC_E_NONE) { 487 cli_out("MSPI: Write Fail\n"); 488 return CMD_FAIL; 489 } 490 /* Dump It */ 491 LOG_VERBOSE(BSL_LS_SOC_COMMON, 492 (BSL_META_U(unit, 493 "%02x\n"), data)); 494 } else { /* Read */ 495 rbytes = 1; 496 LOG_VERBOSE(BSL_LS_SOC_COMMON, 497 (BSL_META_U(unit, 498 "MSPI: Writing %d bytes and Reading %d bytes\n"), 499 wbytes, rbytes)); 500 if (soc_mspi_writeread8(unit, (uint8 *) &wdata[0], wbytes,(uint8 *) &rdata[0], rbytes) != SOC_E_NONE) { 501 cli_out("MSPI: Write-Read Fail\n"); 502 return CMD_FAIL; 503 } 504 data = rdata[0]; 505 LOG_VERBOSE(BSL_LS_SOC_COMMON, 506 (BSL_META_U(unit, 507 "Read %02x\n"), data)); 508 509 if (data_bit_order) { 510 temp = 0; 511 for(i=0; i<8; i++) { 512 if (data & (1<<i)) { 513 temp |= (1<<(7-i)); 514 } 515 } 516 data = temp; 517 } 518 /* Dump It */ 519 cli_out("%02x\n", data); 520 } 521 return rv; 522 } 523 #endif