]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
spi: spi-fsl-dspi: Simplify transfer counter handling
authorEsben Haabendal <eha@deif.com>
Wed, 20 Jun 2018 07:34:34 +0000 (09:34 +0200)
committerMark Brown <broonie@kernel.org>
Wed, 20 Jun 2018 13:46:03 +0000 (14:46 +0100)
Simplify driver by avoiding counter wrapping by clearing transfer counter
on first SPI transfer per interrupt instead of tracking what it was before.

Signed-off-by: Esben Haabendal <eha@deif.com>
Acked-by: Martin Hundebøll <martin@geanix.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-fsl-dspi.c

index c0c3b8bf278142cce8afc6e4ca7466cda42ca504..2371b9978e65dee3df71d312f4c7a2ffeb58e481 100644 (file)
 #define SPI_CS_ASSERT          0x02
 #define SPI_CS_DROP            0x04
 
-#define SPI_TCR_TCNT_MAX       0x10000
-
 #define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000)
 
 struct chip_data {
@@ -201,7 +199,6 @@ struct fsl_dspi {
        wait_queue_head_t       waitq;
        u32                     waitflags;
 
-       u32                     spi_tcnt;
        struct fsl_dspi_dma     *dma;
 };
 
@@ -594,6 +591,10 @@ static int dspi_eoq_write(struct fsl_dspi *dspi)
                        /* request EOQ flag for last transfer in queue */
                        dspi_pushr |= SPI_PUSHR_EOQ;
 
+               /* Clear transfer counter on first transfer (in FIFO) */
+               if (tx_count == 0)
+                       dspi_pushr |= SPI_PUSHR_CTCNT;
+
                regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr);
 
                tx_count++;
@@ -635,6 +636,9 @@ static int dspi_tcfq_write(struct fsl_dspi *dspi)
 
        dspi_pushr = dspi_data_to_pushr(dspi, tx_word);
 
+       /* Clear transfer counter on each transfer */
+       dspi_pushr |= SPI_PUSHR_CTCNT;
+
        regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr);
 
        return tx_word + 1;
@@ -658,10 +662,6 @@ static int dspi_transfer_one_message(struct spi_master *master,
        struct spi_transfer *transfer;
        int status = 0;
        enum dspi_trans_mode trans_mode;
-       u32 spi_tcr;
-
-       regmap_read(dspi->regmap, SPI_TCR, &spi_tcr);
-       dspi->spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr);
 
        message->actual_length = 0;
 
@@ -831,7 +831,7 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
        struct spi_message *msg = dspi->cur_msg;
        enum dspi_trans_mode trans_mode;
        u32 spi_sr, spi_tcr;
-       u32 spi_tcnt, tcnt_diff;
+       u16 spi_tcnt;
        int tx_word;
 
        regmap_read(dspi->regmap, SPI_SR, &spi_sr);
@@ -841,26 +841,15 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
        if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) {
                tx_word = is_double_byte_mode(dspi);
 
+               /* Get transfer counter (in number of SPI transfers). It was
+                * reset to 0 when transfer(s) were started.
+                */
                regmap_read(dspi->regmap, SPI_TCR, &spi_tcr);
                spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr);
-               /*
-                * The width of SPI Transfer Counter in SPI_TCR is 16bits,
-                * so the max couner is 65535. When the counter reach 65535,
-                * it will wrap around, counter reset to zero.
-                * spi_tcnt my be less than dspi->spi_tcnt, it means the
-                * counter already wrapped around.
-                * SPI Transfer Counter is a counter of transmitted frames.
-                * The size of frame maybe two bytes.
-                */
-               tcnt_diff = ((spi_tcnt + SPI_TCR_TCNT_MAX) - dspi->spi_tcnt)
-                       % SPI_TCR_TCNT_MAX;
-               tcnt_diff *= (tx_word + 1);
-               if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM)
-                       tcnt_diff--;
-
-               msg->actual_length += tcnt_diff;
 
-               dspi->spi_tcnt = spi_tcnt;
+               /* Update total number of bytes that were transferred */
+               msg->actual_length += spi_tcnt * (tx_word + 1) -
+                       (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM ? 1 : 0);
 
                trans_mode = dspi->devtype_data->trans_mode;
                switch (trans_mode) {