When needing to send/receive data in small chunks, make this interrupt driven rather than waiting for a completion event for each small section of data. Reviewed-by: Callum Sinclair <callum.sinclair@xxxxxxxxxxxxxxxxxxx> Reviewed-by: Chris Packham <chris.packham@xxxxxxxxxxxxxxxxxxx> Signed-off-by: Mark Tomlinson <mark.tomlinson@xxxxxxxxxxxxxxxxxxx> --- drivers/spi/spi-bcm-qspi.c | 44 ++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index ce30ebf27f06..0cc51bcda300 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -200,12 +200,14 @@ struct bcm_qspi_dev_id { struct qspi_trans { struct spi_transfer *trans; int byte; + int slots; bool mspi_last_trans; }; struct bcm_qspi { struct platform_device *pdev; struct spi_master *master; + struct spi_device *spi_dev; struct clk *clk; u32 base_clk; u32 max_speed_hz; @@ -731,12 +733,14 @@ static inline u16 read_rxram_slot_u16(struct bcm_qspi *qspi, int slot) ((bcm_qspi_read(qspi, MSPI, msb_offset) & 0xff) << 8); } -static void read_from_hw(struct bcm_qspi *qspi, int slots) +static void read_from_hw(struct bcm_qspi *qspi) { struct qspi_trans tp; - int slot; + int slot, slots; bcm_qspi_disable_bspi(qspi); + tp = qspi->trans_pos; + slots = tp.slots; if (slots > MSPI_NUM_CDRAM) { /* should never happen */ @@ -744,8 +748,6 @@ static void read_from_hw(struct bcm_qspi *qspi, int slots) return; } - tp = qspi->trans_pos; - for (slot = 0; slot < slots; slot++) { if (tp.trans->rx_buf) { if (tp.trans->bits_per_word <= 8) { @@ -803,11 +805,12 @@ static inline void write_cdram_slot(struct bcm_qspi *qspi, int slot, u32 val) } /* Return number of slots written */ -static int write_to_hw(struct bcm_qspi *qspi, struct spi_device *spi) +static int write_to_hw(struct bcm_qspi *qspi) { struct qspi_trans tp; int slot = 0, tstatus = 0; u32 mspi_cdram = 0; + struct spi_device *spi = qspi->spi_dev; bcm_qspi_disable_bspi(qspi); tp = qspi->trans_pos; @@ -846,6 +849,9 @@ static int write_to_hw(struct bcm_qspi *qspi, struct spi_device *spi) slot++; } + /* save slot number for read_from_hw() */ + qspi->trans_pos.slots = slot; + if (!slot) { dev_err(&qspi->pdev->dev, "%s: no data to send?", __func__); goto done; @@ -960,24 +966,21 @@ static int bcm_qspi_transfer_one(struct spi_master *master, struct spi_transfer *trans) { struct bcm_qspi *qspi = spi_master_get_devdata(master); - int slots; - unsigned long timeo = msecs_to_jiffies(100); + unsigned long timeo = msecs_to_jiffies(1000); if (!spi->cs_gpiod) bcm_qspi_chip_select(qspi, spi->chip_select); qspi->trans_pos.trans = trans; qspi->trans_pos.byte = 0; + qspi->spi_dev = spi; - while (qspi->trans_pos.byte < trans->len) { - reinit_completion(&qspi->mspi_done); + reinit_completion(&qspi->mspi_done); - slots = write_to_hw(qspi, spi); - if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) { - dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n"); - return -ETIMEDOUT; - } + write_to_hw(qspi); - read_from_hw(qspi, slots); + if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) { + dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n"); + return -ETIMEDOUT; } bcm_qspi_enable_bspi(qspi); @@ -1092,7 +1095,16 @@ static irqreturn_t bcm_qspi_mspi_l2_isr(int irq, void *dev_id) bcm_qspi_write(qspi, MSPI, MSPI_MSPI_STATUS, status); if (qspi->soc_intc) soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_DONE); - complete(&qspi->mspi_done); + + read_from_hw(qspi); + + if (qspi->trans_pos.trans) { + write_to_hw(qspi); + } else { + complete(&qspi->mspi_done); + spi_finalize_current_transfer(qspi->master); + } + return IRQ_HANDLED; } -- 2.27.0