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

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