pcie.c (26826B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * Purpose: PCIe Diagnostics utilities 9 */ 10 #if defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) || (defined(BCM_ESW_SUPPORT) && defined(PCIEG3_DIAG_SUPPORT)) 11 #include <appl/diag/system.h> 12 #include <appl/diag/diag.h> 13 #include <sal/compiler.h> 14 #include <sal/core/thread.h> 15 #include <sal/core/libc.h> 16 #include <soc/error.h> 17 #include <soc/cm.h> 18 #include <soc/iproc.h> 19 #include <soc/cmic.h> 20 #include <soc/cmicx_qspi.h> 21 #ifdef INCLUDE_CPU_I2C 22 #include <sal/appl/i2c.h> 23 #endif 24 #include <sal/core/time.h> 25 #include <soc/mcm/memregs.h> 26 #include <shared/bsl.h> 27 #include <sdk_config.h> 28 #include <soc/soc_flash.h> 29 #include <pcig3_phy_acc.h> 30 31 # define SPI_SPEED 62500000 /* BSPI */ 32 # define SPI_MODE 3 /* (CPOL|CPHA) */ 33 34 #define SWAP_ENDIAN(x) ( \ 35 (((x) << 24) & 0xff000000) | \ 36 (((x) << 8) & 0x00ff0000) | \ 37 (((x) >> 8) & 0x0000ff00) | \ 38 (((x) >> 24) & 0x000000ff)) 39 40 #ifdef INCLUDE_CPU_I2C 41 #define IPROC_ACCESS_READ(unit, addr, read_value_p) iproc_qspi_read(unit, addr, read_value_p) 42 #define IPROC_ACCESS_WRITE(unit, addr, value) iproc_qspi_write(unit, addr, value) 43 #else 44 #define IPROC_ACCESS_READ(unit, addr, rvp) soc_iproc_getreg(unit, addr, rvp) 45 #define IPROC_ACCESS_WRITE(unit, addr, rvp) soc_iproc_setreg(unit, addr, rvp) 46 #endif /* INCLUDE_CPU_I2C */ 47 #define IPROC_ACCESS_METHOD_PCIE 0 /* Access using the 1st PCIe BAR (default) */ 48 #define IPROC_ACCESS_METHOD_I2C 1 /* Access by I2C using specified IDs */ 49 #define IPROC_ACCESS_METHOD_I2C_BDE 2 /* by I2C using the BDE */ 50 51 52 static int 53 pcie_srds_bus_read(void *user_acc, uint32_t addr, uint16_t *val) 54 { 55 srds_access_t *sa = user_acc; 56 int unit = sa->unit; 57 58 if (soc_pcie_phy_read(unit, addr, val) != SOC_E_NONE) { 59 return -1; 60 } 61 62 return 0; 63 } 64 65 static int 66 pcie_srds_bus_write(void *user_acc, uint32_t addr, uint16_t val) 67 { 68 srds_access_t *sa = user_acc; 69 int unit = sa->unit; 70 71 if (soc_pcie_phy_write(unit, addr, val) != SOC_E_NONE) { 72 return -1; 73 } 74 75 return 0; 76 } 77 78 static srds_bus_t pcie_srds_bus = { 79 .name = "pcie_bus_merlin16", 80 .read = pcie_srds_bus_read, 81 .write = pcie_srds_bus_write 82 }; 83 84 static int 85 _pcie_phy_fw_flash_init(int unit, 86 soc_flash_conf_t *flash) 87 { 88 unsigned int speed = SPI_SPEED; 89 unsigned int mode = SPI_MODE; 90 int rv = SOC_E_NONE; 91 92 rv = soc_flash_init(unit, speed, mode, flash); 93 if (SOC_FAILURE(rv)) { 94 cli_out("Error: Init SPI flash speed = %u, mode =%u\n", speed, mode); 95 } 96 return rv; 97 } 98 #ifndef NO_FILEIO 99 STATIC int 100 _pcie_phy_fw_write_block(int unit, 101 uint32 offset, 102 size_t len, 103 const uint8 *buf) 104 { 105 int rv = SOC_E_NONE; 106 #ifdef PCIEFW_QSPI_TEST_PERFORMANCE 107 sal_usecs_t diff; 108 #define PCIEFW_MEASURE_START diff = sal_time_usecs(); 109 #define PCIEFW_MEASURE_END(testname) \ 110 diff = sal_time_usecs() - diff; \ 111 total_##testname += diff; \ 112 if (max_##testname < diff) max_##testname = diff; \ 113 if (min_##testname > diff) min_##testname = diff; 114 #define PCIEFW_MEASURE_END_SINGLE(testname) \ 115 diff = sal_time_usecs() - diff; \ 116 cli_out("%s operation took %u us\n", #testname, diff); 117 #define PCIEFW_MEASURE_SUMMARY(testname) \ 118 cli_out("Test %s min/average/max us: %u/%u/%u\n", #testname, min_ ## testname, \ 119 (total_ ## testname + iters / 2) / iters, max_ ## testname); 120 #else 121 #define PCIEFW_MEASURE_START 122 #define PCIEFW_MEASURE_END(testname) 123 #define PCIEFW_MEASURE_END_SINGLE(testname) 124 #define PCIEFW_MEASURE_SUMMARY(testname) 125 #endif /* PCIEFW_QSPI_TEST_PERFORMANCE */ 126 127 PCIEFW_MEASURE_START; 128 rv = soc_flash_erase(unit, offset, len); 129 PCIEFW_MEASURE_END_SINGLE(erase); 130 131 if (SOC_SUCCESS(rv)) { 132 PCIEFW_MEASURE_START; 133 rv = soc_flash_write(unit, offset, len, buf); 134 PCIEFW_MEASURE_END_SINGLE(write); 135 if (SOC_FAILURE(rv)) { 136 cli_out("Failed to write = 0x%x\n", offset); 137 } 138 } else { 139 cli_out("Failed to erase = 0x%x\n", offset); 140 } 141 142 return rv; 143 } 144 #endif 145 146 STATIC cmd_result_t 147 _pcie_phy_fw_load(int unit, args_t *args) 148 { 149 #ifndef NO_FILEIO 150 #ifdef PCIEFW_QSPI_TEST_PERFORMANCE 151 uint32 iters = 0; 152 sal_usecs_t diff, total_enable = 0, min_enable = -1, max_enable = 0, total_write = 0, min_write = -1, max_write = 0, total_read = 0, min_read = -1, max_read = 0; 153 #define PCIEFW_MEASURE_START diff = sal_time_usecs(); 154 #define PCIEFW_MEASURE_END(testname) \ 155 diff = sal_time_usecs() - diff; \ 156 total_##testname += diff; \ 157 if (max_##testname < diff) max_##testname = diff; \ 158 if (min_##testname > diff) min_##testname = diff; 159 #define PCIEFW_MEASURE_SUMMARY(testname) \ 160 cli_out("Test %s min/average/max us: %u/%u/%u\n", #testname, min_ ## testname, \ 161 (total_ ## testname + iters / 2) / iters, max_ ## testname); 162 #else 163 #define PCIEFW_MEASURE_START 164 #define PCIEFW_MEASURE_END(testname) 165 #endif /* PCIEFW_QSPI_TEST_PERFORMANCE */ 166 int rv = SOC_E_NONE; 167 char *file_str; 168 long len; 169 uint32 offset = 0, val; 170 uint8 *wbuf = NULL; 171 uint8 *rbuf = NULL; 172 soc_flash_conf_t flash; 173 FILE *in = NULL; 174 175 /* Parse command */ 176 if ((file_str = ARG_GET(args)) == NULL) { 177 return CMD_USAGE; 178 } 179 /* initialize the flash driver */ 180 rv = _pcie_phy_fw_flash_init(unit, &flash); 181 if (SOC_FAILURE(rv)) { 182 goto error_init; 183 } 184 wbuf = sal_alloc(flash.sector_size, "FLASH_W"); 185 if (!wbuf) { 186 rv = SOC_E_MEMORY; 187 goto error; 188 } 189 190 rbuf = sal_alloc(flash.sector_size, "FLASH_R"); 191 if (!rbuf) { 192 rv = SOC_E_MEMORY; 193 goto error; 194 } 195 /* Open file and get the file size */ 196 cli_out("Opening file: %s\n", file_str); 197 198 in = sal_fopen(file_str, "r"); 199 if (!in) { 200 /* failure to open existing file is error */ 201 rv = _SHR_E_EXISTS; 202 goto error; 203 } 204 205 sal_fseek(in, 0, SEEK_END); 206 if((len = sal_ftell(in)) == -1) { 207 rv = _SHR_E_INTERNAL; 208 goto error; 209 } 210 if ((sal_fseek(in, 0, SEEK_SET) != 0) || (len == 0)) { 211 rv = _SHR_E_INTERNAL; 212 goto error; 213 } 214 cli_out("Updating PCIE firmware\n"); 215 while (len) { 216 size_t size = (flash.sector_size > len) ? len : flash.sector_size; 217 int i; 218 #ifdef PCIEFW_QSPI_TEST_PERFORMANCE 219 ++iters; 220 #endif /* PCIEFW_QSPI_TEST_PERFORMANCE */ 221 /* Read the sector data */ 222 /* coverity[tainted_data_argument] */ 223 if (sal_fread(wbuf, sizeof(uint8), size, in) != size) { 224 rv = _SHR_E_INTERNAL; 225 goto error; 226 } 227 228 PCIEFW_MEASURE_START 229 rv = soc_flash_cmd_write_status(unit, 0); 230 PCIEFW_MEASURE_END(enable) 231 if (SOC_FAILURE(rv)) { 232 cli_out("Failed to unlock all sectors\n"); 233 break; 234 } 235 PCIEFW_MEASURE_START 236 rv = _pcie_phy_fw_write_block(unit, offset, size, wbuf); 237 PCIEFW_MEASURE_END(write) 238 if (SOC_FAILURE(rv)) { 239 break; 240 } 241 242 /* Read back to verify */ 243 PCIEFW_MEASURE_START 244 rv = soc_flash_read(unit, offset, size, rbuf); 245 PCIEFW_MEASURE_END(read) 246 if (SOC_FAILURE(rv)) { 247 break; 248 } 249 for (i = 0; i < size; i++) { 250 if (wbuf[i] != rbuf[i]) { 251 cli_out("Data Mismatch: offset= 0x%x, write = 0x%x, read = 0x%x\n", 252 i, wbuf[i], rbuf[i]); 253 rv = SOC_E_FAIL; 254 break; 255 } 256 } 257 len = len - size; 258 offset += size; 259 } 260 #ifdef PCIEFW_QSPI_TEST_PERFORMANCE 261 cli_out("Ran %u iterations sector size: %u\n", iters, (unsigned)flash.sector_size); 262 PCIEFW_MEASURE_SUMMARY(enable); 263 PCIEFW_MEASURE_SUMMARY(write); 264 PCIEFW_MEASURE_SUMMARY(read); 265 #endif /* PCIEFW_QSPI_TEST_PERFORMANCE */ 266 if (SOC_SUCCESS(rv)) { 267 /* Clear UC_PROG_DONE bit so updated FW can take effect upon reset */ 268 READ_PAXB_0_GEN3_UC_LOADER_STATUSr(unit, &val); 269 soc_reg_field_set(unit, PAXB_0_GEN3_UC_LOADER_STATUSr, &val, 270 UC_PROG_DONEf, 0); 271 WRITE_PAXB_0_GEN3_UC_LOADER_STATUSr(unit, val); 272 cli_out("PCIE firmware updated successfully. Please reset the system... \n"); 273 } 274 error: 275 /* Close the driver */ 276 soc_flash_cleanup(unit); 277 if (in) { 278 sal_fclose(in); 279 } 280 error_init: 281 if (rbuf) { 282 sal_free(rbuf); 283 } 284 if (wbuf) { 285 /* coverity[tainted_data] */ 286 sal_free(wbuf); 287 } 288 if (SOC_FAILURE(rv)) { 289 return CMD_FAIL; 290 } else { 291 return CMD_OK; 292 } 293 #else 294 cli_out("File system not supported\n"); 295 return CMD_FAIL; 296 #endif 297 } 298 299 #define PCIE_G3_FW_MAGIC_NUM (0x50434549) 300 #define PCIE_GE_FW_HDR_OFFSET (0x2000) 301 302 typedef struct soc_pcieg3_fw_hdr_s{ 303 uint32 magic; /* Magic number to verify if FW is programmed into flash */ 304 uint32 ldrver; /* FW loader version, major version: bits[31-16], minor version: bits[15-0] */ 305 uint32 size; /* FW image size */ 306 uint32 crc; /* FW image CRC */ 307 char version[12]; /* FW version string */ 308 }soc_pcieg3_fw_hdr_t; 309 310 STATIC cmd_result_t 311 _pcie_phy_fw_version(int unit) 312 { 313 soc_pcieg3_fw_hdr_t fwhdr; 314 soc_flash_conf_t flash; 315 uint32 endian = 1; 316 int rv = SOC_E_NONE; 317 318 if(*(uint8 *)(&endian) == 1) 319 endian = 0; 320 321 /* initialize the flash driver */ 322 rv = _pcie_phy_fw_flash_init(unit, &flash); 323 if (SOC_FAILURE(rv)) { 324 goto error_version; 325 } 326 327 rv = soc_flash_read(unit, PCIE_GE_FW_HDR_OFFSET, sizeof(soc_pcieg3_fw_hdr_t), (uint8 *) &fwhdr); 328 if (SOC_FAILURE(rv)) { 329 goto error_version; 330 } 331 332 if(endian) { 333 fwhdr.magic = SWAP_ENDIAN(fwhdr.magic); 334 fwhdr.ldrver = SWAP_ENDIAN(fwhdr.ldrver); 335 fwhdr.size = SWAP_ENDIAN(fwhdr.size); 336 fwhdr.crc = SWAP_ENDIAN(fwhdr.crc); 337 } 338 if(fwhdr.magic == PCIE_G3_FW_MAGIC_NUM) { 339 cli_out("\tPCIe FW loader version: %d.%d\n\tPCIe FW version: %s\n", 340 fwhdr.ldrver >>16, 341 fwhdr.ldrver & 0xffff, 342 fwhdr.version); 343 } 344 else { 345 cli_out("Valid firmware not found\n"); 346 } 347 348 error_version: 349 if (SOC_FAILURE(rv)) { 350 return CMD_FAIL; 351 } else { 352 return CMD_OK; 353 } 354 } 355 356 STATIC cmd_result_t 357 _pcie_phy_fw_set_access_method(int unit, uint8 access_method, uint32 i2c_bus, uint32 i2c_dev) 358 { 359 uint8 bus = 0, dev = 0; 360 if (access_method == QSPI_ACCESS_METHOD_PCIE) { 361 #ifdef INCLUDE_CPU_I2C 362 } else if(access_method == QSPI_ACCESS_METHOD_I2C) { 363 bus = i2c_bus, dev = i2c_dev; 364 } 365 else if (access_method == QSPI_ACCESS_METHOD_I2C_BDE) { 366 #endif /* INCLUDE_CPU_I2C */ 367 } else { 368 cli_out("The specified access mode in not supported\n"); 369 return CMD_USAGE; 370 } 371 iproc_qspi_set_access_method(unit, access_method, bus, dev); 372 return CMD_OK; 373 } 374 375 STATIC cmd_result_t 376 _pcie_phy_fw_access(int unit, args_t *args) 377 { 378 int rv = CMD_FAIL; 379 uint32 address, value = 0; 380 char *cmd_str = ARG_GET(args), *c; 381 382 /* Parse sub-command */ 383 if (cmd_str == NULL) { 384 return CMD_USAGE; 385 } else if (sal_strcasecmp(cmd_str, "pcie") == 0) { 386 rv = _pcie_phy_fw_set_access_method(unit, IPROC_ACCESS_METHOD_PCIE, 0, 0); 387 } else if (sal_strcasecmp(cmd_str, "i2c_bde") == 0) { 388 rv = _pcie_phy_fw_set_access_method(unit, IPROC_ACCESS_METHOD_I2C_BDE, 0, 0); 389 } else if (sal_strcasecmp(cmd_str, "i2c") == 0) { 390 if ((c = ARG_GET(args)) == NULL) { 391 return CMD_USAGE; 392 } 393 address = sal_ctoi(c, 0); /* I2C bus number */ 394 if ((c = ARG_GET(args)) == NULL) { 395 return CMD_USAGE; 396 } 397 value = sal_ctoi(c, 0); /* I2C slave device number */ 398 rv = _pcie_phy_fw_set_access_method(unit, IPROC_ACCESS_METHOD_I2C, address, value); 399 } else if (sal_strcasecmp(cmd_str, "read") == 0) { 400 if ((c = ARG_GET(args)) == NULL) { 401 return CMD_USAGE; 402 } 403 address = sal_ctoi(c, 0); /* AXI address */ 404 if ((rv = IPROC_ACCESS_READ(unit, address, &value)) == SOC_E_NONE) { 405 cli_out("The 4 bytes read from address 0x%x are 0x%x\n", address, value); 406 } else { 407 cli_out("Failed to read from address 0x%x\n", address); 408 } 409 } else if (sal_strcasecmp(cmd_str, "write") == 0) { 410 if ((c = ARG_GET(args)) == NULL) { 411 return CMD_USAGE; 412 } 413 address = sal_ctoi(c, 0); /* AXI address */ 414 if ((c = ARG_GET(args)) == NULL) { 415 return CMD_USAGE; 416 } 417 value = sal_ctoi(c, 0); /* value to write */ 418 if ((rv = IPROC_ACCESS_WRITE(unit, address, value)) == SOC_E_NONE) { 419 cli_out("Wrote 4 bytes read to address 0x%x with the value 0x%x\n", address, value); 420 } else { 421 cli_out("Failed to write to address 0x%x\n", address); 422 } 423 } else if (sal_strcasecmp(cmd_str, "testperf") == 0) { 424 #define PCIEFW_MEASURE_INIT_TEST total = 0; min = -1; max = 0 425 #define PCIEFW_MEASURE_OPERATION_START diff = sal_time_usecs() 426 #define PCIEFW_MEASURE_OPERATION_END \ 427 diff = sal_time_usecs() - diff; \ 428 total += diff; \ 429 if (max < diff) max = diff; \ 430 if (min > diff) min = diff 431 #define PCIEFW_MEASURE_END_TEST(testname, bits) \ 432 cli_out("Test %s results: min/average/max us: %u/%u/%u %uHz\n", #testname, min, \ 433 (total + nof_iters / 2) / nof_iters, max, total >= 100 ? nof_iters * 10000 * (bits) / (total / 100) : 0) 434 435 unsigned i; 436 uint32 value, nof_iters; 437 sal_usecs_t total, diff, min, max; 438 439 if ((c = ARG_GET(args)) == NULL) { 440 return CMD_USAGE; 441 } 442 address = sal_ctoi(c, 0); /* AXI address to use for testing performance */ 443 444 if ((c = ARG_GET(args)) == NULL) { 445 return CMD_USAGE; 446 } 447 nof_iters = sal_ctoi(c, 0); /* number of test iterations */ 448 449 PCIEFW_MEASURE_INIT_TEST; 450 for (i = nof_iters; i; --i) { 451 PCIEFW_MEASURE_OPERATION_START; 452 rv = IPROC_ACCESS_READ(unit, address, &value); 453 PCIEFW_MEASURE_OPERATION_END; 454 if (rv != SOC_E_NONE) { 455 cli_out("Test read number %u failed, from address 0x%x\n", nof_iters + 1 - i, value); 456 return CMD_FAIL; 457 } 458 } 459 PCIEFW_MEASURE_END_TEST("read AXI word", 9 * 8 + 2); 460 461 PCIEFW_MEASURE_INIT_TEST; 462 for (i = nof_iters; i; --i) { 463 PCIEFW_MEASURE_OPERATION_START; 464 rv = IPROC_ACCESS_WRITE(unit, address, value); 465 PCIEFW_MEASURE_OPERATION_END; 466 if (rv != SOC_E_NONE) { 467 cli_out("Test write number %u failed, from address 0x%x\n", nof_iters + 1 - i, value); 468 return CMD_FAIL; 469 } 470 } 471 PCIEFW_MEASURE_END_TEST("write AXI word", 9 * 8 + 2); 472 473 return CMD_OK; 474 } else { 475 return CMD_USAGE; 476 } 477 478 return rv; 479 } 480 481 STATIC cmd_result_t 482 _pcie_phy_fw(int unit, args_t *args) 483 { 484 int rv = CMD_OK; 485 char *cmd_str; 486 487 /* Parse command */ 488 if ((cmd_str = ARG_GET(args)) == NULL) { 489 return CMD_USAGE; 490 } 491 492 if (sal_strcasecmp(cmd_str, "load") == 0) { 493 rv = _pcie_phy_fw_load(unit, args); 494 } else if (sal_strcasecmp(cmd_str, "version") == 0) { 495 rv = _pcie_phy_fw_version(unit); 496 } else if (sal_strcasecmp(cmd_str, "access") == 0) { 497 rv = _pcie_phy_fw_access(unit, args); 498 } 499 else { 500 rv = CMD_FAIL; 501 } 502 503 return rv; 504 } 505 506 STATIC cmd_result_t 507 _pcie_serdes_pram_read(int unit, args_t *args) 508 { 509 char *c; 510 uint32_t address; 511 uint32_t size; 512 srds_access_t sa; 513 514 if ((c= ARG_GET(args)) == NULL) { 515 return CMD_USAGE; 516 } 517 address = sal_ctoi(c, 0); 518 519 if ((c= ARG_GET(args)) == NULL) { 520 return CMD_USAGE; 521 } 522 size = sal_ctoi(c, 0); 523 524 sa.unit = unit; 525 sa.bus = &pcie_srds_bus; 526 527 (void)pcie_phy_diag_pram_read(&sa, address, size); 528 529 return CMD_OK; 530 } 531 532 STATIC cmd_result_t 533 _pcie_get_reg(int unit, args_t *args) 534 { 535 char *c; 536 uint16_t address; 537 uint32_t val; 538 539 if ((c= ARG_GET(args)) == NULL) { 540 return CMD_USAGE; 541 } 542 address = sal_ctoi(c, 0); 543 544 val= 0; 545 WRITE_PAXB_0_CONFIG_IND_ADDRr(unit, address); 546 sal_udelay(1000); 547 READ_PAXB_0_CONFIG_IND_DATAr(unit, &val); 548 cli_out("\nPCIe getepreg: address: 0x%x, data = 0x%x\n", address, val); 549 550 return CMD_OK; 551 } 552 553 STATIC cmd_result_t 554 _pcie_set_reg(int unit, args_t *args) 555 { 556 char *c; 557 uint16_t address; 558 uint32_t val; 559 uint32_t data; 560 561 if ((c= ARG_GET(args)) == NULL) { 562 return CMD_USAGE; 563 } 564 address = sal_ctoi(c, 0); 565 566 val= 0; 567 568 WRITE_PAXB_0_CONFIG_IND_ADDRr(unit, address); 569 sal_udelay(1000); 570 if ((c= ARG_GET(args)) == NULL) { 571 return CMD_USAGE; 572 } 573 data = sal_ctoi(c, 0); 574 WRITE_PAXB_0_CONFIG_IND_DATAr(unit, data); 575 sal_udelay(1000); 576 577 WRITE_PAXB_0_CONFIG_IND_ADDRr(unit, address); 578 sal_udelay(1000); 579 READ_PAXB_0_CONFIG_IND_DATAr(unit, &val); 580 cli_out("\nPCIe setepreg: address: 0x%x, data = 0x%x\n", address, val); 581 582 return CMD_OK; 583 } 584 585 /* Arguments: address, field data, field mask, field bit shift(left) */ 586 STATIC cmd_result_t 587 _pcie_rmw_reg(int unit, args_t *args) 588 { 589 char *c; 590 uint16_t address, fdata, fmask, fshift; 591 uint32_t iaddr, data; 592 593 if ((c= ARG_GET(args)) == NULL) { 594 return CMD_USAGE; 595 } 596 address = sal_ctoi(c, 0); 597 598 if ((c= ARG_GET(args)) == NULL) { 599 return CMD_USAGE; 600 } 601 fdata = sal_ctoi(c, 0); 602 603 if ((c= ARG_GET(args)) == NULL) { 604 return CMD_USAGE; 605 } 606 fmask = sal_ctoi(c, 0); 607 608 if ((c= ARG_GET(args)) == NULL) { 609 return CMD_USAGE; 610 } 611 fshift = sal_ctoi(c, 0); 612 613 iaddr = address; 614 /* Read register */ 615 WRITE_PAXB_0_CONFIG_IND_ADDRr(unit, iaddr); 616 sal_udelay(1000); 617 READ_PAXB_0_CONFIG_IND_DATAr(unit, &data); 618 619 /* modify data */ 620 data &= fmask << fshift; 621 data |= (fdata & fmask) << fshift; 622 623 /* Write data */ 624 WRITE_PAXB_0_CONFIG_IND_ADDRr(unit, iaddr); 625 sal_udelay(1000); 626 WRITE_PAXB_0_CONFIG_IND_DATAr(unit, data); 627 628 /* Read back data */ 629 WRITE_PAXB_0_CONFIG_IND_ADDRr(unit, iaddr); 630 sal_udelay(1000); 631 READ_PAXB_0_CONFIG_IND_DATAr(unit, &data); 632 633 cli_out("\nPCIe modepreg: address: 0x%x, data = 0x%x\n", address, data); 634 635 return CMD_OK; 636 } 637 638 /* 639 * Diagnostic utilities for serdes and PHY devices. 640 * 641 * Command format used in BCM diag shell: 642 * phy diag <pbm> <sub_cmd> [sub cmd parameters] 643 * The list of sub commands: 644 * dsc - display tx/rx equalization information. 645 * dsc - display Diag information 646 * BCM.0> pciephy diag <lane bit map> dsc 647 * BCM.0> pciephy diag <lane bit map> state 648 * BCM.0> pciephy diag <lane bit map> eyescan 649 */ 650 STATIC cmd_result_t 651 _pcie_phy_diag(int unit, args_t *args) 652 { 653 int rv; 654 char *cmd_str, *lane_str; 655 soc_pbmp_t pbmp; 656 soc_port_t port; 657 srds_access_t *sa, *sa_l = NULL; 658 int core = 0, prev_core = -1; 659 int lane = 0, count = 0; 660 661 /* Parse lane bitmap */ 662 if ((lane_str= ARG_GET(args)) == NULL) { 663 return CMD_USAGE; 664 } 665 (void)parse_pbmp(unit, lane_str, &pbmp); 666 667 /* Parse command */ 668 if ((cmd_str = ARG_GET(args)) == NULL) { 669 return CMD_USAGE; 670 } 671 672 sa = sal_alloc(sizeof(srds_access_t) * PCIE_MAX_CORES, "access array"); 673 if (NULL == sa) { 674 cli_out("_pcie_phy_diag: memory allocation failed/n"); 675 return CMD_FAIL; 676 } 677 678 SOC_PBMP_ITER(pbmp, port) { 679 core = port / 4; 680 lane = port % 4; 681 if (core != prev_core) { 682 prev_core = core; 683 if(sa_l == NULL) { 684 sa_l = sa; 685 } 686 else { 687 sa_l++; 688 } 689 sa_l->unit = unit; 690 sa_l->core = core; 691 sa_l->lane_mask = 0; 692 sa_l->bus = &pcie_srds_bus; 693 count++; 694 } 695 if (sa_l != NULL) { 696 sa_l->lane_mask |= 0x1 << lane; 697 } 698 } 699 700 if (sal_strcasecmp(cmd_str, "dsc") == 0) { 701 rv = pcie_phy_diag_dsc(sa, count); 702 if (rv != SRDS_E_NONE) { 703 cli_out("pcie_phy_diag_dsc() failed, Error: %d\n", rv); 704 } 705 } else if (sal_strcasecmp(cmd_str, "eyescan") == 0) { 706 rv = pcie_phy_diag_eyescan(sa, count); 707 if (rv != SRDS_E_NONE) { 708 cli_out("pcie_phy_diag_eyescan() failed, Error: %d\n", rv); 709 } 710 } else if (sal_strcasecmp(cmd_str, "state") == 0) { 711 rv = pcie_phy_diag_state(sa, count); 712 if (rv != SRDS_E_NONE) { 713 cli_out("pcie_phy_diag_state() failed, Error: %d\n", rv); 714 } 715 } else { 716 sal_free(sa); 717 return CMD_FAIL; 718 } 719 720 sal_free(sa); 721 return CMD_OK; 722 } 723 724 725 char pciephy_usage[] = 726 "Usages:\n\t" 727 #ifdef COMPILER_STRING_CONST_LIMIT 728 "pciephy <sub_cmd> [sub cmd parameters]\n\t" 729 "Default: None\n" 730 "Subcommands: diag, fw\n"; 731 #else 732 "Parameters: <sub_cmd> [sub cmd parameters]\n\t" 733 "The list of sub commands:\n\t" 734 " getreg - displays value of given phy register\n\t" 735 " Syntax: pciephy getreg <PHY register address>\n\t" 736 " Example:\n\t" 737 " BCM.0> pciephy getreg 0xd230\n\t" 738 " setreg - writes given value into given phy register\n\t" 739 " Syntax: pciephy setreg <PHY register address> <value>\n\t" 740 " Example:\n\t" 741 " BCM.0> pciephy setreg 0xd230 0xa555\n\t" 742 " getepreg - displays value of given pcie core(endpoint) register\n\t" 743 " Syntax: pciephy getepreg <pcie core register address>\n\t" 744 " Example:\n\t" 745 " BCM.0> pciephy getepreg 0xbc\n\t" 746 " setepreg - writes given value into given pcie core(endpoint) register\n\t" 747 " Syntax: pciephy setepreg <pcie core register address> <value>\n\t" 748 " Example:\n\t" 749 " BCM.0> pciephy setepreg 0xbc 0x12345678\n\t" 750 " pramread - Reads and displays pcie phy pram content at given address\n\t" 751 " Syntax: pciephy pramread <pram address offset> <number of 16-bit words to read>\n\t" 752 " Example:\n\t" 753 " BCM.0> pciephy pramread 0x0 0x20\n\t" 754 " diag - display SerDes lane information.\n\t" 755 " Syntax: pciephy diag <lane bit map> <diag sub-command>\n\t" 756 " Example:\n\t" 757 " BCM.0> pciephy diag 0x1 dsc\n\t" 758 " BCM.0> pciephy diag 0x1 state\n\t" 759 " BCM.0> pciephy diag 0x1 eyescan\n\t" 760 " diag - sub commands:\n\t" 761 " dsc - Display core state and lane state\n\t" 762 " state - Discplay core state, lane state for all lanes and event log\n\t" 763 " eyescan - Display eyescan for selected lane\n\t" 764 " fw - Load SerDes(PCIe Gen3) firmware, display firmware version\n\t" 765 " Syntax: pciephy fw <fw sub-command> [fw sub cmd parameters]\n\t" 766 " Example:\n\t" 767 " BCM.0> pciephy fw load <firmware file>\n\t" 768 " fw - sub commands:\n\t" 769 " load - programs contents of given firmware file to QSPI flash\n\t" 770 " version - displays PCIe Gen3 fw loader and SerDes fw versions\n\t" 771 " access - sets the method used to access the firmware or tests it. sub commands:\n\t" 772 " pcie - (default) Use the device's PCIe connection for access\n\t" 773 " i2c_bde - Use the device's BDE I2C functions for access\n\t" 774 " i2c <I2C bus number> <slave device ID> - Use I2C using the give bus and device IDs\n\t" 775 " read <AXI address> - read four bytes using the current access method\n\t" 776 " write <AXI address> <value> - write four bytes using the current access method\n" 777 ; 778 #endif 779 780 /* 781 * Function: cmd_pciephy 782 * Purpose: Show/configure PCIe phy registers. 783 * Parameters: u - SOC unit # 784 * a - pointer to args 785 * Returns: CMD_OK/CMD_FAIL/ 786 */ 787 cmd_result_t cmd_pciephy(int u, args_t *a) 788 { 789 char *c; 790 uint16_t address, data; 791 srds_access_t sa; 792 int rv = 0; 793 794 if (SOC_IS_HELIX5(u) && (soc_cm_get_bus_type(u) & SOC_AXI_DEV_TYPE)) { 795 /* HX5 supports PCIe EP mode only and PCIe diag support is not 796 required when running on internal processor */ 797 cli_out("pciephy command NOT supported on this device\n"); 798 ARG_DISCARD(a); 799 return CMD_OK; 800 } 801 802 if (!sh_check_attached(ARG_CMD(a), u)) { 803 return CMD_FAIL; 804 } 805 806 c = ARG_GET(a); 807 808 if (c != NULL && sal_strcasecmp(c, "fw") == 0) { 809 return _pcie_phy_fw(u, a); 810 } 811 if (c != NULL && sal_strcasecmp(c, "diag") == 0) { 812 return _pcie_phy_diag(u, a); 813 } 814 if (c != NULL && sal_strcasecmp(c, "getreg") == 0) { 815 if ((c= ARG_GET(a)) == NULL) { 816 return CMD_USAGE; 817 } 818 address = sal_ctoi(c, 0); 819 sa.unit = u; 820 sa.bus = &pcie_srds_bus; 821 rv = pcie_phy_diag_reg_read(&sa, address, &data); 822 if(rv != 0) { 823 cli_out("pcie_phy_diag_reg_read failed: %d\n", rv); 824 } 825 else { 826 cli_out("\naddess: 0x%x, data = 0x%x\n", address, data); 827 } 828 return CMD_OK; 829 } 830 if (c != NULL && sal_strcasecmp(c, "setreg") == 0) { 831 sa.unit = u; 832 sa.bus = &pcie_srds_bus; 833 if ((c= ARG_GET(a)) == NULL) { 834 return CMD_USAGE; 835 } 836 address = sal_ctoi(c, 0); 837 if ((c= ARG_GET(a)) == NULL) { 838 return CMD_USAGE; 839 } 840 data = sal_ctoi(c, 0); 841 rv = pcie_phy_diag_reg_write(&sa, address, data); 842 if(rv != 0) { 843 cli_out("ERROR: pcie_diag_reg_write failed: %d\n", rv); 844 } 845 else { 846 cli_out("\naddess: 0x%x, data = 0x%x\n", address, data); 847 } 848 return CMD_OK; 849 } 850 if (c != NULL && sal_strcasecmp(c, "getepreg") == 0) { 851 return _pcie_get_reg(u, a); 852 } 853 if (c != NULL && sal_strcasecmp(c, "setepreg") == 0) { 854 return _pcie_set_reg(u, a); 855 } 856 if (c != NULL && sal_strcasecmp(c, "modepreg") == 0) { 857 return _pcie_rmw_reg(u, a); 858 } 859 if (c != NULL && sal_strcasecmp(c, "pramread") == 0) { 860 return _pcie_serdes_pram_read(u, a); 861 } 862 if (c == NULL) { 863 return (CMD_USAGE); 864 } 865 else { 866 cli_out("Command NOT supported\n"); 867 } 868 return CMD_OK; 869 } 870 871 #else 872 /* To avoid empty file warning in not supported architectures */ 873 int appl_diag_diag_anchor; 874 #endif /* #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_ESW_SUPPORT) */ 875