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 */