Skip to content

Commit 1f257b9

Browse files
tlebbroonie
authored andcommitted
spi: cadence-qspi: add no-IRQ mode to indirect reads
Support reads through polling, without any IRQ. The main reason is performance; profiling shows that the first IRQ comes quickly on our specific hardware. Once this IRQ arrives, we poll until all data is retrieved. Avoid initial sleep to reduce IRQ count. Hide this behavior behind a quirk flag. This is confirmed through micro-benchmarks, but also end-to-end performance tests. Mobileye EyeQ5, octal flash, reading 235M on a UBIFS filesystem: - No optimizations, ~10.34s, ~22.7 MB/s, 199230 IRQs - CQSPI_SLOW_SRAM, ~10.34s, ~22.7 MB/s, 70284 IRQs - CQSPI_RD_NO_IRQ, ~9.37s, ~25.1 MB/s, 521 IRQs Signed-off-by: Théo Lebrun <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 3bf64a2 commit 1f257b9

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

drivers/spi/spi-cadence-quadspi.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ static_assert(CQSPI_MAX_CHIPSELECT <= SPI_CS_CNT_MAX);
4242
#define CQSPI_NO_SUPPORT_WR_COMPLETION BIT(3)
4343
#define CQSPI_SLOW_SRAM BIT(4)
4444
#define CQSPI_NEEDS_APB_AHB_HAZARD_WAR BIT(5)
45+
#define CQSPI_RD_NO_IRQ BIT(6)
4546

4647
/* Capabilities */
4748
#define CQSPI_SUPPORTS_OCTAL BIT(0)
@@ -702,6 +703,7 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
702703
const size_t n_rx)
703704
{
704705
struct cqspi_st *cqspi = f_pdata->cqspi;
706+
bool use_irq = !(cqspi->ddata && cqspi->ddata->quirks & CQSPI_RD_NO_IRQ);
705707
struct device *dev = &cqspi->pdev->dev;
706708
void __iomem *reg_base = cqspi->iobase;
707709
void __iomem *ahb_base = cqspi->ahb_base;
@@ -725,17 +727,20 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
725727
* all the read interrupts disabled for max performance.
726728
*/
727729

728-
if (!cqspi->slow_sram)
730+
if (use_irq && cqspi->slow_sram)
731+
writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);
732+
else if (use_irq)
729733
writel(CQSPI_IRQ_MASK_RD, reg_base + CQSPI_REG_IRQMASK);
730734
else
731-
writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);
735+
writel(0, reg_base + CQSPI_REG_IRQMASK);
732736

733737
reinit_completion(&cqspi->transfer_complete);
734738
writel(CQSPI_REG_INDIRECTRD_START_MASK,
735739
reg_base + CQSPI_REG_INDIRECTRD);
736740

737741
while (remaining > 0) {
738-
if (!wait_for_completion_timeout(&cqspi->transfer_complete,
742+
if (use_irq &&
743+
!wait_for_completion_timeout(&cqspi->transfer_complete,
739744
msecs_to_jiffies(CQSPI_READ_TIMEOUT_MS)))
740745
ret = -ETIMEDOUT;
741746

@@ -777,7 +782,7 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
777782
bytes_to_read = cqspi_get_rd_sram_level(cqspi);
778783
}
779784

780-
if (remaining > 0) {
785+
if (use_irq && remaining > 0) {
781786
reinit_completion(&cqspi->transfer_complete);
782787
if (cqspi->slow_sram)
783788
writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);

0 commit comments

Comments
 (0)