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

cmicx_qspi.c (17635B)


      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  * Purpose:     CMICX QSPI driver
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <sal/core/libc.h>
     13 #include <soc/mem.h>
     14 #include <soc/error.h>
     15 #include <soc/register.h>
     16 #include <shared/alloc.h>
     17 #include <sal/core/spl.h>
     18 #include <sal/core/sync.h>
     19 #include <sal/core/dpc.h>
     20 #include <soc/drv.h>
     21 #include <soc/debug.h>
     22 #include <soc/cm.h>
     23 #include <soc/iproc.h>
     24 #include <soc/cmicx_qspi.h>
     25 
     26 #ifdef INCLUDE_CPU_I2C
     27  #include <soc/i2c.h>
     28 #endif
     29 
     30 #ifdef BCM_CMICX_SUPPORT
     31 #include <soc/cmicx.h>
     32 
     33 #ifdef PCIEFW_QSPI_TEST_PERFORMANCE
     34 #include <sal/core/time.h>
     35 #endif
     36 
     37 /* Chip attributes */
     38 #define SPBR_MIN                            8U
     39 #define SPBR_MAX                            255U
     40 #define NUM_TXRAM                           32
     41 #define NUM_RXRAM                           32
     42 #define NUM_CDRAM                           16
     43 
     44 /*
     45  * Register fields
     46  */
     47 #define MSPI_SPCR0_MSB_BITS_8               (0x00000020)
     48 #define BSPI_RAF_CONTROL_START_MASK         (0x00000001)
     49 #define BSPI_RAF_STATUS_SESSION_BUSY_MASK   (0x00000001)
     50 #define BSPI_RAF_STATUS_FIFO_EMPTY_MASK     (0x00000002)
     51 #define BSPI_BITS_PER_PHASE_ADDR_MARK       (0x00010000)
     52 #define BSPI_BITS_PER_CYCLE_DATA_SHIFT      0
     53 #define BSPI_BITS_PER_CYCLE_ADDR_SHIFT      16
     54 
     55 /* SPI transfer flags */
     56 #define SPI_RW_BEGIN 0x01
     57 #define SPI_RW_END   0x02
     58 
     59 
     60 /* Configurations */
     61 
     62 #define QSPI_WAIT_TIMEOUT                   200U    /* msec */
     63 #ifndef IPROC_BSPI_READ_DUMMY_CYCLES
     64 #define IPROC_BSPI_READ_DUMMY_CYCLES 0x8
     65 #endif
     66 #ifndef IPROC_BSPI_READ_CMD
     67 #define IPROC_BSPI_READ_CMD 0xb
     68 #endif
     69 
     70 #ifndef IPROC_BSPI_DATA_LANES
     71 #define IPROC_BSPI_DATA_LANES 4
     72 #endif
     73 
     74 #ifndef IPROC_BSPI_ADDR_LANES
     75 #define IPROC_BSPI_ADDR_LANES 4
     76 #endif
     77 
     78 /* 429 MHz */
     79 #define IPROC_SYS_CLOCK        429
     80 /* 15 Mhz */
     81 #define IPROC_SCL_BAUD_RATE    15
     82 
     83 #ifdef INCLUDE_CPU_I2C
     84 #define IPROC_QSPI_READ(unit, reg, read_value_p) \
     85     iproc_qspi_read(unit, soc_reg_addr(unit, reg, REG_PORT_ANY, 0), read_value_p)
     86 #define IPROC_QSPI_WRITE(unit, reg, value) \
     87     iproc_qspi_write(unit, soc_reg_addr(unit, reg, REG_PORT_ANY, 0), value)
     88 #else
     89 #define IPROC_QSPI_READ(unit, reg, rvp) \
     90         soc_iproc_getreg(unit, soc_reg_addr(unit, reg, REG_PORT_ANY, 0), rvp)
     91 #define IPROC_QSPI_WRITE(unit, reg, rv) \
     92         soc_iproc_setreg(unit, soc_reg_addr(unit, reg, REG_PORT_ANY, 0), rv)
     93 #endif /* INCLUDE_CPU_I2C */
     94 
     95 #define LMAX(a, b) (((a) > (b)) ? (a) : (b))
     96 #define LMIN(a, b) (((a) < (b)) ? (a) : (b))
     97 
     98 
     99 /* MSPI registers */
    100 typedef struct qspi_mspi_hw_s {
    101     uint32 txram;
    102     uint32 rxram;
    103     uint32 cdram;
    104 } qspi_mspi_hw_t;
    105 
    106 /* State */
    107 typedef enum cmicx_qspi_state_s {
    108     QSPI_STATE_DISABLED,
    109     QSPI_STATE_MSPI,
    110     QSPI_STATE_BSPI
    111 } cmicx_qspi_state_t;
    112 
    113 /* QSPI configuration data */
    114 typedef struct cmicx_qspi_conf_s {
    115     /* Specified SPI parameters */
    116     uint32 max_hz;
    117     uint32 spi_mode;
    118     /* State */
    119     cmicx_qspi_state_t state;
    120     uint8 bspi_op;
    121     uint32 bspi_addr;
    122     int mspi_16bit;
    123     int mode_4byte;
    124     uint32 bspi_hw;
    125     qspi_mspi_hw_t mspi_hw[NUM_TXRAM];
    126 } cmicx_qspi_conf_t;
    127 
    128 typedef struct cmicx_qspi_s {
    129     cmicx_qspi_conf_t *conf;
    130     sal_mutex_t lock;
    131     uint8 access_method; /* method to access the device for QSPI flash memory access */
    132     uint8 i2c_bus;       /* I2C bus number for QSPI_ACCESS_METHOD_I2C */
    133     uint8 i2c_dev;       /* I2C slave device number for QSPI_ACCESS_METHOD_I2C */
    134 } cmicx_qspi_t;
    135 
    136 
    137 STATIC qspi_mspi_hw_t mspi_hw[NUM_TXRAM] = {
    138     {QSPI_MSPI_TXRAM00r, QSPI_MSPI_RXRAM00r, QSPI_MSPI_CDRAM00r},
    139     {QSPI_MSPI_TXRAM01r, QSPI_MSPI_RXRAM01r, QSPI_MSPI_CDRAM01r}, 
    140     {QSPI_MSPI_TXRAM02r, QSPI_MSPI_RXRAM02r, QSPI_MSPI_CDRAM02r},
    141     {QSPI_MSPI_TXRAM03r, QSPI_MSPI_RXRAM03r, QSPI_MSPI_CDRAM03r},
    142     {QSPI_MSPI_TXRAM04r, QSPI_MSPI_RXRAM04r, QSPI_MSPI_CDRAM04r},
    143     {QSPI_MSPI_TXRAM05r, QSPI_MSPI_RXRAM05r, QSPI_MSPI_CDRAM05r}, 
    144     {QSPI_MSPI_TXRAM06r, QSPI_MSPI_RXRAM06r, QSPI_MSPI_CDRAM06r},
    145     {QSPI_MSPI_TXRAM07r, QSPI_MSPI_RXRAM07r, QSPI_MSPI_CDRAM07r},
    146     {QSPI_MSPI_TXRAM08r, QSPI_MSPI_RXRAM08r, QSPI_MSPI_CDRAM08r},
    147     {QSPI_MSPI_TXRAM09r, QSPI_MSPI_RXRAM09r, QSPI_MSPI_CDRAM09r}, 
    148     {QSPI_MSPI_TXRAM10r, QSPI_MSPI_RXRAM10r, QSPI_MSPI_CDRAM10r},
    149     {QSPI_MSPI_TXRAM11r, QSPI_MSPI_RXRAM11r, QSPI_MSPI_CDRAM11r},
    150     {QSPI_MSPI_TXRAM12r, QSPI_MSPI_RXRAM12r, QSPI_MSPI_CDRAM12r},
    151     {QSPI_MSPI_TXRAM13r, QSPI_MSPI_RXRAM13r, QSPI_MSPI_CDRAM13r}, 
    152     {QSPI_MSPI_TXRAM14r, QSPI_MSPI_RXRAM14r, QSPI_MSPI_CDRAM14r},
    153     {QSPI_MSPI_TXRAM15r, QSPI_MSPI_RXRAM15r, QSPI_MSPI_CDRAM15r},
    154     {QSPI_MSPI_TXRAM16r, QSPI_MSPI_RXRAM16r, 0},
    155     {QSPI_MSPI_TXRAM17r, QSPI_MSPI_RXRAM17r, 0},
    156     {QSPI_MSPI_TXRAM18r, QSPI_MSPI_RXRAM18r, 0},
    157     {QSPI_MSPI_TXRAM19r, QSPI_MSPI_RXRAM19r, 0},
    158     {QSPI_MSPI_TXRAM20r, QSPI_MSPI_RXRAM20r, 0},
    159     {QSPI_MSPI_TXRAM21r, QSPI_MSPI_RXRAM21r, 0},
    160     {QSPI_MSPI_TXRAM22r, QSPI_MSPI_RXRAM22r, 0},
    161     {QSPI_MSPI_TXRAM23r, QSPI_MSPI_RXRAM23r, 0},
    162     {QSPI_MSPI_TXRAM24r, QSPI_MSPI_RXRAM24r, 0},
    163     {QSPI_MSPI_TXRAM25r, QSPI_MSPI_RXRAM25r, 0},
    164     {QSPI_MSPI_TXRAM26r, QSPI_MSPI_RXRAM26r, 0},
    165     {QSPI_MSPI_TXRAM27r, QSPI_MSPI_RXRAM27r, 0},
    166     {QSPI_MSPI_TXRAM28r, QSPI_MSPI_RXRAM28r, 0},
    167     {QSPI_MSPI_TXRAM29r, QSPI_MSPI_RXRAM29r, 0},
    168     {QSPI_MSPI_TXRAM30r, QSPI_MSPI_RXRAM30r, 0},
    169     {QSPI_MSPI_TXRAM31r, QSPI_MSPI_RXRAM31r, 0},
    170 };
    171 
    172 STATIC cmicx_qspi_t cmicx_qspi[SOC_MAX_NUM_DEVICES] = {{0}};
    173 
    174 /* Set the current QSPI access method */
    175 void
    176 iproc_qspi_set_access_method(int unit, uint8 access_method, uint8 i2c_bus, uint8 i2c_dev)
    177 {
    178     cmicx_qspi_t  *qspi = cmicx_qspi + unit;
    179     qspi->access_method = access_method;
    180     qspi->i2c_bus = i2c_bus;
    181     qspi->i2c_dev = i2c_dev;
    182 }
    183 
    184 #ifdef INCLUDE_CPU_I2C
    185 /* Read a uint32 from the AXI address space using the current QSPI access method */
    186 int
    187 iproc_qspi_read(int unit, uint32 addr, uint32 *read_value)
    188 {
    189     cmicx_qspi_t  *qspi = cmicx_qspi + unit;
    190 
    191     if (qspi->access_method == QSPI_ACCESS_METHOD_PCIE) {
    192         return soc_iproc_getreg(unit, addr, read_value);
    193     } else if (qspi->access_method == QSPI_ACCESS_METHOD_I2C) {
    194         return cpu_i2c_device_read(qspi->i2c_bus, qspi->i2c_dev, addr, read_value);
    195     } else if (qspi->access_method == QSPI_ACCESS_METHOD_I2C_BDE) {
    196         return soc_cm_i2c_device_read(unit, addr, read_value);
    197     }
    198     return SOC_E_INTERNAL;
    199 }
    200 
    201 /* Write a uint32 from the AXI address space using the current QSPI access method */
    202 int
    203 iproc_qspi_write(int unit, uint32 addr, uint32 value)
    204 {
    205     cmicx_qspi_t  *qspi = cmicx_qspi + unit;
    206 
    207     if (qspi->access_method == QSPI_ACCESS_METHOD_PCIE) {
    208         return soc_iproc_setreg(unit, addr, value);
    209     } else if (qspi->access_method == QSPI_ACCESS_METHOD_I2C) {
    210         return cpu_i2c_device_write(qspi->i2c_bus, qspi->i2c_dev, addr, value);
    211     } else if (qspi->access_method == QSPI_ACCESS_METHOD_I2C_BDE) {
    212         return soc_cm_i2c_device_write(unit, addr, value);
    213     }
    214     return SOC_E_INTERNAL;
    215 }
    216 #endif /* INCLUDE_CPU_I2C */
    217 
    218 int
    219 cmicx_qspi_init(int unit,
    220               uint32 max_hz,
    221               uint32 mode)
    222 {
    223     cmicx_qspi_conf_t *conf = NULL;
    224     cmicx_qspi_t  *qspi = &cmicx_qspi[unit];
    225     uint32 spbr;
    226     uint32 val;
    227     int rv = SOC_E_NONE;
    228 
    229     /* Check if already initialized */
    230 
    231     if (qspi->conf != NULL) {
    232         rv = SOC_E_INIT;
    233         goto error;
    234     }
    235 
    236     conf = sal_alloc(sizeof(*conf), "SOC_SPI");
    237     if (conf == NULL) {
    238         rv = SOC_E_MEMORY;
    239         goto error;
    240     }
    241 
    242     if ((qspi->lock =
    243         sal_mutex_create("qspi_lock")) == NULL) {
    244         rv = SOC_E_MEMORY;
    245         goto error;
    246     }
    247     conf->max_hz = max_hz;
    248     conf->spi_mode = mode;
    249     conf->state = QSPI_STATE_DISABLED;
    250     conf->mode_4byte = 0;
    251     sal_memcpy(conf->mspi_hw, mspi_hw, sizeof(mspi_hw));
    252 
    253 
    254     /* BSPI: clock configuration */
    255     IPROC_QSPI_READ(unit, CRU_CONTROLr, &val);
    256     val &= ~0x00000006;
    257     if (conf->max_hz >= 62500000) {
    258         val |= 0x00000006;
    259     } else if (conf->max_hz >= 50000000) {
    260         val |= 0x00000002;
    261     } else if (conf->max_hz >= 31250000) {
    262         val |= 0x00000004;
    263     }
    264     IPROC_QSPI_WRITE(unit, CRU_CONTROLr, val);
    265 
    266     /* BSPI: configure for dual/quad mode */
    267     if (IPROC_BSPI_DATA_LANES != 1 || 
    268         IPROC_BSPI_ADDR_LANES != 1) {
    269         /* Disable flex mode first */
    270         val = 0;
    271         IPROC_QSPI_WRITE(unit, QSPI_BSPI_REGISTERS_FLEX_MODE_ENABLEr, val);
    272         /* Data / Address lanes */
    273         IPROC_QSPI_WRITE(unit, QSPI_BSPI_REGISTERS_BITS_PER_CYCLEr, val);
    274         if (IPROC_BSPI_DATA_LANES == 4) {
    275             val |= 2 << BSPI_BITS_PER_CYCLE_DATA_SHIFT;
    276         } else {
    277             val |= ((IPROC_BSPI_DATA_LANES - 1) 
    278                     << BSPI_BITS_PER_CYCLE_DATA_SHIFT);
    279         }
    280         if (IPROC_BSPI_ADDR_LANES == 4) {
    281             val |= 2 << BSPI_BITS_PER_CYCLE_ADDR_SHIFT;
    282         } else {
    283             val |= ((IPROC_BSPI_ADDR_LANES - 1) 
    284                     << BSPI_BITS_PER_CYCLE_ADDR_SHIFT);
    285         }
    286         IPROC_QSPI_WRITE(unit, QSPI_BSPI_REGISTERS_BITS_PER_CYCLEr, val);
    287         /* Dummy cycles */
    288         IPROC_QSPI_READ(unit, QSPI_BSPI_REGISTERS_BITS_PER_PHASEr, &val);
    289         val &= ~0xFF;
    290         val |= IPROC_BSPI_READ_DUMMY_CYCLES;
    291         IPROC_QSPI_WRITE(unit, QSPI_BSPI_REGISTERS_BITS_PER_PHASEr, val);
    292         /* Command byte for BSPI */
    293         val = IPROC_BSPI_READ_CMD;
    294         IPROC_QSPI_WRITE(unit, QSPI_BSPI_REGISTERS_CMD_AND_MODE_BYTEr, val);
    295         /* Enable flex mode to take effect */
    296         val = 1;
    297         IPROC_QSPI_WRITE(unit, QSPI_BSPI_REGISTERS_FLEX_MODE_ENABLEr, val);
    298     }
    299     /* MSPI: Basic hardware initialization */
    300     IPROC_QSPI_WRITE(unit, QSPI_MSPI_SPCR1_LSBr, 0);
    301     IPROC_QSPI_WRITE(unit, QSPI_MSPI_SPCR1_MSBr, 0);
    302     IPROC_QSPI_WRITE(unit, QSPI_MSPI_NEWQPr, 0);
    303     IPROC_QSPI_WRITE(unit, QSPI_MSPI_ENDQPr, 0);
    304     IPROC_QSPI_WRITE(unit, QSPI_MSPI_SPCR2r, 0);
    305     /*TBD: MSPI: SCK configuration */
    306     spbr = (IPROC_SYS_CLOCK) / (2 * IPROC_SCL_BAUD_RATE);
    307     spbr = LMAX(LMIN(spbr, SPBR_MAX), SPBR_MIN);
    308     IPROC_QSPI_WRITE(unit, QSPI_MSPI_SPCR0_LSBr, spbr);
    309 
    310     /* MSPI: Mode configuration (8 bits by default) */
    311     conf->mspi_16bit = 0;
    312     val = 0x80 |                      /* Master */
    313          (8 << 2) |                  /* 8 bits per word */
    314          (conf->spi_mode & 3);        /* mode: CPOL / CPHA */
    315 
    316     IPROC_QSPI_WRITE(unit, QSPI_MSPI_SPCR0_MSBr, val);
    317 
    318     qspi->conf = conf;
    319 
    320     return rv;
    321 
    322 error:
    323     if (conf) {
    324         sal_free(conf);
    325     }
    326     return SOC_E_NONE;
    327 }
    328 
    329 int 
    330 cmicx_qspi_cleanup(int unit)
    331 {
    332     cmicx_qspi_t  *qspi = &cmicx_qspi[unit];
    333 
    334     if (qspi->conf == NULL) {
    335         return SOC_E_PARAM;
    336     }
    337     if (qspi->lock) { 
    338         sal_mutex_destroy(qspi->lock);
    339         qspi->lock = 0;
    340     }
    341     sal_free(qspi->conf);
    342     qspi->conf = NULL;
    343     return SOC_E_NONE;
    344 }
    345 
    346 static void 
    347 bspi_flush_prefetch_buffers(int unit)
    348 {
    349     IPROC_QSPI_WRITE(unit, QSPI_BSPI_REGISTERS_B0_CTRLr, 0);
    350     IPROC_QSPI_WRITE(unit, QSPI_BSPI_REGISTERS_B1_CTRLr, 0);
    351     IPROC_QSPI_WRITE(unit, QSPI_BSPI_REGISTERS_B0_CTRLr, 1);
    352     IPROC_QSPI_WRITE(unit, QSPI_BSPI_REGISTERS_B1_CTRLr, 1);
    353 }
    354 
    355 static int 
    356 disable_mspi(int unit, cmicx_qspi_conf_t *conf)
    357 {
    358     if (conf->state == QSPI_STATE_BSPI) {
    359         return SOC_E_NONE;
    360     }
    361     /* Disable write lock */
    362     IPROC_QSPI_WRITE(unit, QSPI_MSPI_WRITE_LOCKr, 0);
    363     /* Flush prefetch buffers */
    364     bspi_flush_prefetch_buffers(unit);
    365     /* Switch to BSPI */
    366     IPROC_QSPI_WRITE(unit, QSPI_BSPI_REGISTERS_MAST_N_BOOT_CTRLr, 0);
    367     /* Update state */
    368     conf->state = QSPI_STATE_BSPI;
    369 
    370     return SOC_E_NONE;
    371 }
    372 
    373 static int 
    374 enable_mspi(int unit, cmicx_qspi_conf_t *conf)
    375 {
    376     soc_timeout_t to;
    377     uint32 val;
    378 
    379     if (conf->state == QSPI_STATE_MSPI) {
    380         return SOC_E_NONE;
    381     }
    382     /* Switch to MSPI if not yet */
    383     IPROC_QSPI_READ(unit, QSPI_BSPI_REGISTERS_MAST_N_BOOT_CTRLr, &val);
    384 
    385     if ((val & 0x01) == 0) {
    386         soc_timeout_init(&to, QSPI_WAIT_TIMEOUT * 1000, 1);
    387         while(1) {
    388             IPROC_QSPI_READ(unit, QSPI_BSPI_REGISTERS_BUSY_STATUSr, &val);
    389             if ((val & 0x01) == 0) {
    390                 IPROC_QSPI_WRITE(unit, QSPI_BSPI_REGISTERS_MAST_N_BOOT_CTRLr, 1);
    391                 sal_usleep(1);
    392                 break;
    393             }
    394             if (soc_timeout_check(&to)) {
    395                 break;
    396             }
    397         }
    398         IPROC_QSPI_READ(unit, QSPI_BSPI_REGISTERS_MAST_N_BOOT_CTRLr, &val);
    399         if (val != 0x01) {
    400             return SOC_E_FAIL;
    401         }
    402     }
    403     /* Update state */
    404     conf->state = QSPI_STATE_MSPI;
    405 
    406     return SOC_E_NONE;
    407 }
    408 
    409 int
    410 cmicx_qspi_claim_bus(int unit)
    411 {
    412     cmicx_qspi_t *qspi = &cmicx_qspi[unit];
    413     cmicx_qspi_conf_t *conf = qspi->conf;
    414     int rv = SOC_E_NONE;
    415 
    416     if (conf == NULL) {
    417         return SOC_E_PARAM;
    418     }
    419     /* Switch to MSPI by default */
    420     rv = enable_mspi(unit, conf);
    421 
    422     return rv;
    423 }
    424 
    425 int 
    426 cmicx_qspi_release_bus(int unit)
    427 {
    428     cmicx_qspi_t *qspi = &cmicx_qspi[unit];
    429     cmicx_qspi_conf_t *conf = qspi->conf;
    430 
    431     if (conf == NULL) {
    432         return SOC_E_PARAM;
    433     }
    434     /* Make sure no operation is in progress */
    435     IPROC_QSPI_WRITE(unit, QSPI_MSPI_SPCR2r, 0);
    436     sal_usleep(1);
    437     /* Switch to BSPI */
    438     disable_mspi(unit, conf);
    439     /* Update state */
    440     conf->state = QSPI_STATE_DISABLED;
    441 
    442     return SOC_E_NONE;
    443 }
    444 
    445 static int
    446 mspi_rw(int unit, cmicx_qspi_conf_t *conf,
    447           uint32 bytes, const uint8 *tx,
    448           uint8 *rx, int end)
    449 {
    450     uint32 val;
    451 #ifdef PCIEFW_QSPI_TEST_PERFORMANCE
    452     sal_usecs_t diff;
    453 #define PCIEFW_MEASURE_START diff = sal_time_usecs();
    454 #define PCIEFW_MEASURE_END(testname) \
    455     diff = sal_time_usecs() - diff; \
    456     cli_out("    %s: %uus\n", #testname, diff);
    457 #else
    458 #define PCIEFW_MEASURE_START
    459 #define PCIEFW_MEASURE_END(testname)
    460 #endif /* PCIEFW_QSPI_TEST_PERFORMANCE */
    461 
    462     PCIEFW_MEASURE_START;
    463     IPROC_QSPI_READ(unit, QSPI_MSPI_SPCR0_MSBr, &val);
    464     /* Use 8-bit queue for odd-bytes transfer */
    465     val |= MSPI_SPCR0_MSB_BITS_8; 
    466     IPROC_QSPI_WRITE(unit, QSPI_MSPI_SPCR0_MSBr, val);
    467     PCIEFW_MEASURE_END(mspi_rw_1_QSPI_MSPI_SPCR0_MSB_modify);
    468     conf->mspi_16bit = 0;
    469 
    470     while(bytes) {
    471         uint32 chunk;
    472         uint32 queues;
    473         uint32 i;
    474         soc_timeout_t to;
    475 
    476         /* Determine how many bytes to process this time */
    477         chunk = LMIN(bytes, NUM_CDRAM);
    478         queues = chunk;
    479         bytes -= chunk;
    480         /* Fill CDRAMs and TXRAMS */
    481         PCIEFW_MEASURE_START;
    482         for(i=0; i<chunk; i++) {
    483             IPROC_QSPI_WRITE(unit, conf->mspi_hw[i].cdram, 0x82);
    484             IPROC_QSPI_WRITE(unit, conf->mspi_hw[i << 1].txram,
    485                               tx ? tx[i] : 0xff);
    486         }
    487         PCIEFW_MEASURE_END(mspi_rw_2_write_chunk_loop);
    488         /* Setup queue pointers */
    489         PCIEFW_MEASURE_START;
    490         IPROC_QSPI_WRITE(unit, QSPI_MSPI_NEWQPr, 0);
    491         IPROC_QSPI_WRITE(unit, QSPI_MSPI_ENDQPr, (queues - 1));
    492 
    493         /* Deassert CS if requested and it's the last transfer */
    494         if (bytes == 0 && end ) {
    495             IPROC_QSPI_WRITE(unit, conf->mspi_hw[queues - 1].cdram, 0x02);
    496         }
    497         /* Kick off */
    498         IPROC_QSPI_WRITE(unit, QSPI_MSPI_MSPI_STATUSr, 0);
    499         IPROC_QSPI_WRITE(unit, QSPI_MSPI_SPCR2r, 0xc0);    /* cont | spe */
    500         PCIEFW_MEASURE_END(mspi_rw_3_after_chunk);
    501         /* Wait for completion */
    502         soc_timeout_init(&to, QSPI_WAIT_TIMEOUT * 1000, 1);
    503         PCIEFW_MEASURE_START;
    504         while(1) {
    505             IPROC_QSPI_READ(unit, QSPI_MSPI_MSPI_STATUSr, &val);
    506             if (val & 0x01) {
    507                 break;
    508             }
    509             if (soc_timeout_check(&to)) {
    510                 break;
    511             }
    512         }
    513         PCIEFW_MEASURE_END(mspi_rw_4_wait_for_QSPI_MSPI_MSPI_STATUS);
    514         if ((val & 0x01) == 0) {
    515             return -SOC_E_FAIL;
    516         }
    517         /* Read data out */
    518         if (rx) {
    519             PCIEFW_MEASURE_START;
    520             for(i=0; i<chunk; i++) {
    521                 IPROC_QSPI_READ(unit,
    522                      conf->mspi_hw[(i << 1) + 1].rxram, &val);
    523                 rx[i] = val & 0xff;
    524             }
    525             PCIEFW_MEASURE_END(mspi_rw_5_wait_for_read_chunk_loop);
    526         }
    527         /* Advance pointers */
    528         if (tx)
    529             tx += chunk;
    530         if (rx) 
    531             rx += chunk;
    532     }
    533 
    534     return SOC_E_NONE;
    535 }
    536 
    537 int
    538 cmicx_qspi_rw(int unit,
    539               uint32 bytes,
    540               const void *dout,
    541               void *din,
    542               uint32 flags)
    543 {
    544     cmicx_qspi_t *qspi = &cmicx_qspi[unit];
    545     cmicx_qspi_conf_t *conf = qspi->conf;
    546     uint8 *rx = din;
    547     const uint8 *tx = dout;
    548     int rv  = SOC_E_NONE;
    549 #ifdef PCIEFW_QSPI_TEST_PERFORMANCE
    550     sal_usecs_t diff;
    551 #endif /* PCIEFW_QSPI_TEST_PERFORMANCE */
    552 
    553     if (conf == NULL) {
    554         return SOC_E_PARAM;
    555     }
    556     /* MSPI: Enable write lock at the beginning */
    557     if (flags & SPI_RW_BEGIN) {
    558         /* Switch to MSPI if not yet */
    559         rv = enable_mspi(unit, conf);
    560         if (SOC_FAILURE(rv)) {
    561             return -rv;
    562         }
    563         IPROC_QSPI_WRITE(unit, QSPI_MSPI_WRITE_LOCKr, 1);
    564     }
    565     /* MSPI: Transfer it */
    566     if (bytes) {
    567         if(tx || rx) {
    568             PCIEFW_MEASURE_START;
    569             rv = mspi_rw(unit, conf, bytes, tx, rx, (flags & SPI_RW_END));
    570             PCIEFW_MEASURE_END(cmicx_qspi_rw_mspi_rw);
    571         } else {
    572             rv = SOC_E_PARAM;
    573         }
    574     }
    575     /* MSPI: Disable write lock if it's done */
    576     if (flags & SPI_RW_END) {
    577         IPROC_QSPI_WRITE(unit, QSPI_MSPI_WRITE_LOCKr, 0);
    578     }
    579 
    580     return rv;
    581 }
    582 
    583 #endif /* BCM_CMICX_SUPPORT */