spi: bcm2835aux: unifying code between polling and interrupt driven code [Linux 4.14.143]

This Linux kernel change "spi: bcm2835aux: unifying code between polling and interrupt driven code" is included in the Linux 4.14.143 release. This change is authored by Martin Sperl <kernel [at] martin.sperl.org> on Sat Mar 30 09:30:58 2019 +0000. The commit for this change in Linux stable tree is 3bd81fd (patch) which is from upstream commit 7188a6f. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 7188a6f.

spi: bcm2835aux: unifying code between polling and interrupt driven code

[ Upstream commit 7188a6f0eee3f1fae5d826cfc6d569657ff950ec ]

Sharing more code between polling and interrupt-driven mode.

Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>

There are 51 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/spi/spi-bcm2835aux.c | 51 ++++++++++++++++----------------------------
 1 file changed, 18 insertions(+), 33 deletions(-)

diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c
index bd00b7c..97cb3be 100644
--- a/drivers/spi/spi-bcm2835aux.c
+++ b/drivers/spi/spi-bcm2835aux.c
@@ -178,23 +178,13 @@ static void bcm2835aux_spi_reset_hw(struct bcm2835aux_spi *bs)
              BCM2835_AUX_SPI_CNTL0_CLEARFIFO);
 }

-static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
+static void bcm2835aux_spi_transfer_helper(struct bcm2835aux_spi *bs)
 {
-   struct spi_master *master = dev_id;
-   struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
-   irqreturn_t ret = IRQ_NONE;
-
-   /* IRQ may be shared, so return if our interrupts are disabled */
-   if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) &
-         (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE)))
-       return ret;
-
    /* check if we have data to read */
    while (bs->rx_len &&
           (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
          BCM2835_AUX_SPI_STAT_RX_EMPTY))) {
        bcm2835aux_rd_fifo(bs);
-       ret = IRQ_HANDLED;
    }

    /* check if we have data to write */
@@ -203,7 +193,6 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
           (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
          BCM2835_AUX_SPI_STAT_TX_FULL))) {
        bcm2835aux_wr_fifo(bs);
-       ret = IRQ_HANDLED;
    }

    /* and check if we have reached "done" */
@@ -211,8 +200,21 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
           (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
          BCM2835_AUX_SPI_STAT_BUSY))) {
        bcm2835aux_rd_fifo(bs);
-       ret = IRQ_HANDLED;
    }
+}
+
+static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
+{
+   struct spi_master *master = dev_id;
+   struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+
+   /* IRQ may be shared, so return if our interrupts are disabled */
+   if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) &
+         (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE)))
+       return IRQ_NONE;
+
+   /* do common fifo handling */
+   bcm2835aux_spi_transfer_helper(bs);

    if (!bs->tx_len) {
        /* disable tx fifo empty interrupt */
@@ -226,8 +228,7 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
        complete(&master->xfer_completion);
    }

-   /* and return */
-   return ret;
+   return IRQ_HANDLED;
 }

 static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
@@ -273,7 +274,6 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
 {
    struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
    unsigned long timeout;
-   u32 stat;

    /* configure spi */
    bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
@@ -284,24 +284,9 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,

    /* loop until finished the transfer */
    while (bs->rx_len) {
-       /* read status */
-       stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT);
-
-       /* fill in tx fifo with remaining data */
-       if ((bs->tx_len) && (!(stat & BCM2835_AUX_SPI_STAT_TX_FULL))) {
-           bcm2835aux_wr_fifo(bs);
-           continue;
-       }

-       /* read data from fifo for both cases */
-       if (!(stat & BCM2835_AUX_SPI_STAT_RX_EMPTY)) {
-           bcm2835aux_rd_fifo(bs);
-           continue;
-       }
-       if (!(stat & BCM2835_AUX_SPI_STAT_BUSY)) {
-           bcm2835aux_rd_fifo(bs);
-           continue;
-       }
+       /* do common fifo handling */
+       bcm2835aux_spi_transfer_helper(bs);

        /* there is still data pending to read check the timeout */
        if (bs->rx_len && time_after(jiffies, timeout)) {

Leave a Reply

Your email address will not be published. Required fields are marked *