Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi: fsl-espi: eliminate need for linearization when reading from hardware

Eliminate need for linearization when reading from the hardware and
write to the transfer buffers directly.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Heiner Kallweit and committed by
Mark Brown
dcb425f3 05823432

+63 -14
+63 -14
drivers/spi/spi-fsl-espi.c
··· 102 102 struct spi_transfer *tx_t; 103 103 unsigned int tx_pos; 104 104 bool tx_done; 105 + struct spi_transfer *rx_t; 106 + unsigned int rx_pos; 107 + bool rx_done; 105 108 106 109 bool swab; 107 110 unsigned int rx_len; ··· 126 123 static inline u32 fsl_espi_read_reg(struct fsl_espi *espi, int offset) 127 124 { 128 125 return ioread32be(espi->reg_base + offset); 126 + } 127 + 128 + static inline u16 fsl_espi_read_reg16(struct fsl_espi *espi, int offset) 129 + { 130 + return ioread16(espi->reg_base + offset); 129 131 } 130 132 131 133 static inline u8 fsl_espi_read_reg8(struct fsl_espi *espi, int offset) ··· 336 328 static void fsl_espi_read_rx_fifo(struct fsl_espi *espi, u32 events) 337 329 { 338 330 u32 rx_fifo_avail = SPIE_RXCNT(events); 331 + unsigned int rx_left; 332 + void *rx_buf; 339 333 340 - while (rx_fifo_avail >= min(4U, espi->rx_len) && espi->rx_len) 341 - if (espi->rx_len >= 4) { 342 - *(u32 *)espi->rx = fsl_espi_read_reg(espi, ESPI_SPIRF); 343 - espi->rx += 4; 344 - espi->rx_len -= 4; 334 + start: 335 + rx_left = espi->rx_t->len - espi->rx_pos; 336 + rx_buf = espi->rx_t->rx_buf; 337 + while (rx_fifo_avail >= min(4U, rx_left) && rx_left) { 338 + if (rx_left >= 4) { 339 + u32 val = fsl_espi_read_reg(espi, ESPI_SPIRF); 340 + 341 + if (rx_buf && espi->swab) 342 + *(u32 *)(rx_buf + espi->rx_pos) = swahb32(val); 343 + else if (rx_buf) 344 + *(u32 *)(rx_buf + espi->rx_pos) = val; 345 + espi->rx_pos += 4; 346 + rx_left -= 4; 345 347 rx_fifo_avail -= 4; 348 + } else if (rx_left >= 2 && rx_buf && espi->swab) { 349 + u16 val = fsl_espi_read_reg16(espi, ESPI_SPIRF); 350 + 351 + *(u16 *)(rx_buf + espi->rx_pos) = swab16(val); 352 + espi->rx_pos += 2; 353 + rx_left -= 2; 354 + rx_fifo_avail -= 2; 346 355 } else { 347 - *(u8 *)espi->rx = fsl_espi_read_reg8(espi, ESPI_SPIRF); 348 - espi->rx += 1; 349 - espi->rx_len -= 1; 356 + u8 val = fsl_espi_read_reg8(espi, ESPI_SPIRF); 357 + 358 + if (rx_buf) 359 + *(u8 *)(rx_buf + espi->rx_pos) = val; 360 + espi->rx_pos += 1; 361 + rx_left -= 1; 350 362 rx_fifo_avail -= 1; 351 363 } 364 + } 365 + 366 + if (!rx_left) { 367 + if (list_is_last(&espi->rx_t->transfer_list, 368 + espi->m_transfers)) { 369 + espi->rx_done = true; 370 + return; 371 + } 372 + espi->rx_t = list_next_entry(espi->rx_t, transfer_list); 373 + espi->rx_pos = 0; 374 + /* continue with next transfer if rx fifo is not empty */ 375 + if (rx_fifo_avail) 376 + goto start; 377 + } 352 378 } 353 379 354 380 static void fsl_espi_setup_transfer(struct spi_device *spi, ··· 417 375 static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) 418 376 { 419 377 struct fsl_espi *espi = spi_master_get_devdata(spi->master); 378 + unsigned int rx_len = t->len; 420 379 u32 mask, spcom; 421 380 int ret; 422 381 ··· 438 395 spcom |= SPCOM_RXSKIP(espi->rxskip); 439 396 espi->tx_len = espi->rxskip; 440 397 espi->rx_len = t->len - espi->rxskip; 398 + rx_len = t->len - espi->rxskip; 441 399 espi->rx = t->rx_buf + espi->rxskip; 442 400 if (t->rx_nbits == SPI_NBITS_DUAL) 443 401 spcom |= SPCOM_DO; ··· 448 404 449 405 /* enable interrupts */ 450 406 mask = SPIM_DON; 451 - if (espi->rx_len > FSL_ESPI_FIFO_SIZE) 407 + if (rx_len > FSL_ESPI_FIFO_SIZE) 452 408 mask |= SPIM_RXT; 453 409 fsl_espi_write_reg(espi, ESPI_SPIM, mask); 454 410 ··· 482 438 transfer_list); 483 439 espi->tx_pos = 0; 484 440 espi->tx_done = false; 441 + espi->rx_t = list_first_entry(&m->transfers, struct spi_transfer, 442 + transfer_list); 443 + espi->rx_pos = 0; 444 + espi->rx_done = false; 485 445 486 446 espi->rxskip = fsl_espi_check_rxskip_mode(m); 487 447 if (trans->rx_nbits == SPI_NBITS_DUAL && !espi->rxskip) { 488 448 dev_err(espi->dev, "Dual output mode requires RXSKIP mode!\n"); 489 449 return -EINVAL; 490 450 } 451 + 452 + /* In RXSKIP mode skip first transfer for reads */ 453 + if (espi->rxskip) 454 + espi->rx_t = list_next_entry(espi->rx_t, transfer_list); 491 455 492 456 fsl_espi_copy_to_buf(m, espi); 493 457 fsl_espi_setup_transfer(spi, trans); ··· 504 452 505 453 if (trans->delay_usecs) 506 454 udelay(trans->delay_usecs); 507 - 508 - if (!ret) 509 - fsl_espi_copy_from_buf(m, espi); 510 455 511 456 return ret; 512 457 } ··· 605 556 606 557 static void fsl_espi_cpu_irq(struct fsl_espi *espi, u32 events) 607 558 { 608 - if (espi->rx_len) 559 + if (!espi->rx_done) 609 560 fsl_espi_read_rx_fifo(espi, events); 610 561 611 562 if (!espi->tx_done) 612 563 fsl_espi_fill_tx_fifo(espi, events); 613 564 614 - if (!espi->tx_done || espi->rx_len) 565 + if (!espi->tx_done || !espi->rx_done) 615 566 return; 616 567 617 568 /* we're done, but check for errors before returning */