[PATCH 4/5] spi: bcm-qspi: Make multiple data blocks interrupt-driven

From: Mark Tomlinson
Date: Mon Jun 15 2020 - 00:06:26 EST


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