Merge branch 'spi-5.4' into spi-next
authorMark Brown <broonie@kernel.org>
Sun, 15 Sep 2019 09:32:06 +0000 (10:32 +0100)
committerMark Brown <broonie@kernel.org>
Sun, 15 Sep 2019 09:32:06 +0000 (10:32 +0100)
1  2 
drivers/spi/spi-bcm2835.c
drivers/spi/spi-dw-pci.c
drivers/spi/spi-uniphier.c

index dfdcebb38830a795e8a3676d19fc788cca1dcef5,8a0ea465cbe0562367b716cef03370562bbf2d7d..b4070c0de3dff56fd172271a98109351c28824d3
@@@ -25,7 -25,9 +25,9 @@@
  #include <linux/of.h>
  #include <linux/of_address.h>
  #include <linux/of_device.h>
- #include <linux/of_gpio.h>
+ #include <linux/gpio/consumer.h>
+ #include <linux/gpio/machine.h> /* FIXME: using chip internals */
+ #include <linux/gpio/driver.h> /* FIXME: using chip internals */
  #include <linux/of_irq.h>
  #include <linux/spi/spi.h>
  
@@@ -66,6 -68,7 +68,7 @@@
  #define BCM2835_SPI_FIFO_SIZE         64
  #define BCM2835_SPI_FIFO_SIZE_3_4     48
  #define BCM2835_SPI_DMA_MIN_LENGTH    96
+ #define BCM2835_SPI_NUM_CS            3   /* raise as necessary */
  #define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
                                | SPI_NO_CS | SPI_3WIRE)
  
@@@ -92,7 -95,8 +95,8 @@@ MODULE_PARM_DESC(polling_limit_us
   * @rx_prologue: bytes received without DMA if first RX sglist entry's
   *    length is not a multiple of 4 (to overcome hardware limitation)
   * @tx_spillover: whether @tx_prologue spills over to second TX sglist entry
-  * @dma_pending: whether a DMA transfer is in progress
+  * @prepare_cs: precalculated CS register value for ->prepare_message()
+  *    (uses slave-specific clock polarity and phase settings)
   * @debugfs_dir: the debugfs directory - neede to remove debugfs when
   *      unloading the module
   * @count_transfer_polling: count of how often polling mode is used
   *      These are counted as well in @count_transfer_polling and
   *      @count_transfer_irq
   * @count_transfer_dma: count how often dma mode is used
+  * @chip_select: SPI slave currently selected
+  *    (used by bcm2835_spi_dma_tx_done() to write @clear_rx_cs)
+  * @tx_dma_active: whether a TX DMA descriptor is in progress
+  * @rx_dma_active: whether a RX DMA descriptor is in progress
+  *    (used by bcm2835_spi_dma_tx_done() to handle a race)
+  * @fill_tx_desc: preallocated TX DMA descriptor used for RX-only transfers
+  *    (cyclically copies from zero page to TX FIFO)
+  * @fill_tx_addr: bus address of zero page
+  * @clear_rx_desc: preallocated RX DMA descriptor used for TX-only transfers
+  *    (cyclically clears RX FIFO by writing @clear_rx_cs to CS register)
+  * @clear_rx_addr: bus address of @clear_rx_cs
+  * @clear_rx_cs: precalculated CS register value to clear RX FIFO
+  *    (uses slave-specific clock polarity and phase settings)
   */
  struct bcm2835_spi {
        void __iomem *regs;
        int tx_prologue;
        int rx_prologue;
        unsigned int tx_spillover;
-       unsigned int dma_pending;
+       u32 prepare_cs[BCM2835_SPI_NUM_CS];
  
        struct dentry *debugfs_dir;
        u64 count_transfer_polling;
        u64 count_transfer_irq;
        u64 count_transfer_irq_after_polling;
        u64 count_transfer_dma;
+       u8 chip_select;
+       unsigned int tx_dma_active;
+       unsigned int rx_dma_active;
+       struct dma_async_tx_descriptor *fill_tx_desc;
+       dma_addr_t fill_tx_addr;
+       struct dma_async_tx_descriptor *clear_rx_desc[BCM2835_SPI_NUM_CS];
+       dma_addr_t clear_rx_addr;
+       u32 clear_rx_cs[BCM2835_SPI_NUM_CS] ____cacheline_aligned;
  };
  
  #if defined(CONFIG_DEBUG_FS)
@@@ -319,13 -345,6 +345,13 @@@ static void bcm2835_spi_reset_hw(struc
                BCM2835_SPI_CS_INTD |
                BCM2835_SPI_CS_DMAEN |
                BCM2835_SPI_CS_TA);
 +      /*
 +       * Transmission sometimes breaks unless the DONE bit is written at the
 +       * end of every transfer.  The spec says it's a RO bit.  Either the
 +       * spec is wrong and the bit is actually of type RW1C, or it's a
 +       * hardware erratum.
 +       */
 +      cs |= BCM2835_SPI_CS_DONE;
        /* and reset RX/TX FIFOS */
        cs |= BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX;
  
@@@ -455,14 -474,14 +481,14 @@@ static void bcm2835_spi_transfer_prolog
        bs->rx_prologue  = 0;
        bs->tx_spillover = false;
  
-       if (!sg_is_last(&tfr->tx_sg.sgl[0]))
+       if (bs->tx_buf && !sg_is_last(&tfr->tx_sg.sgl[0]))
                bs->tx_prologue = sg_dma_len(&tfr->tx_sg.sgl[0]) & 3;
  
-       if (!sg_is_last(&tfr->rx_sg.sgl[0])) {
+       if (bs->rx_buf && !sg_is_last(&tfr->rx_sg.sgl[0])) {
                bs->rx_prologue = sg_dma_len(&tfr->rx_sg.sgl[0]) & 3;
  
                if (bs->rx_prologue > bs->tx_prologue) {
-                       if (sg_is_last(&tfr->tx_sg.sgl[0])) {
+                       if (!bs->tx_buf || sg_is_last(&tfr->tx_sg.sgl[0])) {
                                bs->tx_prologue  = bs->rx_prologue;
                        } else {
                                bs->tx_prologue += 4;
                bcm2835_wr_fifo_count(bs, bs->rx_prologue);
                bcm2835_wait_tx_fifo_empty(bs);
                bcm2835_rd_fifo_count(bs, bs->rx_prologue);
 -              bcm2835_spi_reset_hw(ctlr);
 +              bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_RX
 +                                                | BCM2835_SPI_CS_CLEAR_TX
 +                                                | BCM2835_SPI_CS_DONE);
  
                dma_sync_single_for_device(ctlr->dma_rx->device->dev,
                                           sg_dma_address(&tfr->rx_sg.sgl[0]),
                sg_dma_len(&tfr->rx_sg.sgl[0])     -= bs->rx_prologue;
        }
  
+       if (!bs->tx_buf)
+               return;
        /*
         * Write remaining TX prologue.  Adjust first entry in TX sglist.
         * Also adjust second entry if prologue spills over to it.
                                                  | BCM2835_SPI_CS_DMAEN);
                bcm2835_wr_fifo_count(bs, tx_remaining);
                bcm2835_wait_tx_fifo_empty(bs);
 -              bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_TX);
 +              bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_TX
 +                                                | BCM2835_SPI_CS_DONE);
        }
  
        if (likely(!bs->tx_spillover)) {
@@@ -541,6 -560,9 +570,9 @@@ static void bcm2835_spi_undo_prologue(s
                sg_dma_len(&tfr->rx_sg.sgl[0])     += bs->rx_prologue;
        }
  
+       if (!bs->tx_buf)
+               goto out;
        if (likely(!bs->tx_spillover)) {
                sg_dma_address(&tfr->tx_sg.sgl[0]) -= bs->tx_prologue;
                sg_dma_len(&tfr->tx_sg.sgl[0])     += bs->tx_prologue;
                sg_dma_address(&tfr->tx_sg.sgl[1]) -= 4;
                sg_dma_len(&tfr->tx_sg.sgl[1])     += 4;
        }
+ out:
+       bs->tx_prologue = 0;
  }
  
- static void bcm2835_spi_dma_done(void *data)
+ /**
+  * bcm2835_spi_dma_rx_done() - callback for DMA RX channel
+  * @data: SPI master controller
+  *
+  * Used for bidirectional and RX-only transfers.
+  */
+ static void bcm2835_spi_dma_rx_done(void *data)
  {
        struct spi_controller *ctlr = data;
        struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
  
-       /* reset fifo and HW */
-       bcm2835_spi_reset_hw(ctlr);
-       /* and terminate tx-dma as we do not have an irq for it
+       /* terminate tx-dma as we do not have an irq for it
         * because when the rx dma will terminate and this callback
         * is called the tx-dma must have finished - can't get to this
         * situation otherwise...
         */
-       if (cmpxchg(&bs->dma_pending, true, false)) {
-               dmaengine_terminate_async(ctlr->dma_tx);
-               bcm2835_spi_undo_prologue(bs);
-       }
+       dmaengine_terminate_async(ctlr->dma_tx);
+       bs->tx_dma_active = false;
+       bs->rx_dma_active = false;
+       bcm2835_spi_undo_prologue(bs);
+       /* reset fifo and HW */
+       bcm2835_spi_reset_hw(ctlr);
  
        /* and mark as completed */;
        complete(&ctlr->xfer_completion);
  }
  
+ /**
+  * bcm2835_spi_dma_tx_done() - callback for DMA TX channel
+  * @data: SPI master controller
+  *
+  * Used for TX-only transfers.
+  */
+ static void bcm2835_spi_dma_tx_done(void *data)
+ {
+       struct spi_controller *ctlr = data;
+       struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
+       /* busy-wait for TX FIFO to empty */
+       while (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE))
+               bcm2835_wr(bs, BCM2835_SPI_CS,
+                          bs->clear_rx_cs[bs->chip_select]);
+       bs->tx_dma_active = false;
+       smp_wmb();
+       /*
+        * In case of a very short transfer, RX DMA may not have been
+        * issued yet.  The onus is then on bcm2835_spi_transfer_one_dma()
+        * to terminate it immediately after issuing.
+        */
+       if (cmpxchg(&bs->rx_dma_active, true, false))
+               dmaengine_terminate_async(ctlr->dma_rx);
+       bcm2835_spi_undo_prologue(bs);
+       bcm2835_spi_reset_hw(ctlr);
+       complete(&ctlr->xfer_completion);
+ }
+ /**
+  * bcm2835_spi_prepare_sg() - prepare and submit DMA descriptor for sglist
+  * @ctlr: SPI master controller
+  * @spi: SPI slave
+  * @tfr: SPI transfer
+  * @bs: BCM2835 SPI controller
+  * @is_tx: whether to submit DMA descriptor for TX or RX sglist
+  *
+  * Prepare and submit a DMA descriptor for the TX or RX sglist of @tfr.
+  * Return 0 on success or a negative error number.
+  */
  static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr,
+                                 struct spi_device *spi,
                                  struct spi_transfer *tfr,
+                                 struct bcm2835_spi *bs,
                                  bool is_tx)
  {
        struct dma_chan *chan;
                chan  = ctlr->dma_tx;
                nents = tfr->tx_sg.nents;
                sgl   = tfr->tx_sg.sgl;
-               flags = 0 /* no  tx interrupt */;
+               flags = tfr->rx_buf ? 0 : DMA_PREP_INTERRUPT;
        } else {
                dir   = DMA_DEV_TO_MEM;
                chan  = ctlr->dma_rx;
        if (!desc)
                return -EINVAL;
  
-       /* set callback for rx */
+       /*
+        * Completion is signaled by the RX channel for bidirectional and
+        * RX-only transfers; else by the TX channel for TX-only transfers.
+        */
        if (!is_tx) {
-               desc->callback = bcm2835_spi_dma_done;
+               desc->callback = bcm2835_spi_dma_rx_done;
                desc->callback_param = ctlr;
+       } else if (!tfr->rx_buf) {
+               desc->callback = bcm2835_spi_dma_tx_done;
+               desc->callback_param = ctlr;
+               bs->chip_select = spi->chip_select;
        }
  
        /* submit it to DMA-engine */
        return dma_submit_error(cookie);
  }
  
+ /**
+  * bcm2835_spi_transfer_one_dma() - perform SPI transfer using DMA engine
+  * @ctlr: SPI master controller
+  * @spi: SPI slave
+  * @tfr: SPI transfer
+  * @cs: CS register
+  *
+  * For *bidirectional* transfers (both tx_buf and rx_buf are non-%NULL), set up
+  * the TX and RX DMA channel to copy between memory and FIFO register.
+  *
+  * For *TX-only* transfers (rx_buf is %NULL), copying the RX FIFO's contents to
+  * memory is pointless.  However not reading the RX FIFO isn't an option either
+  * because transmission is halted once it's full.  As a workaround, cyclically
+  * clear the RX FIFO by setting the CLEAR_RX bit in the CS register.
+  *
+  * The CS register value is precalculated in bcm2835_spi_setup().  Normally
+  * this is called only once, on slave registration.  A DMA descriptor to write
+  * this value is preallocated in bcm2835_dma_init().  All that's left to do
+  * when performing a TX-only transfer is to submit this descriptor to the RX
+  * DMA channel.  Latency is thereby minimized.  The descriptor does not
+  * generate any interrupts while running.  It must be terminated once the
+  * TX DMA channel is done.
+  *
+  * Clearing the RX FIFO is paced by the DREQ signal.  The signal is asserted
+  * when the RX FIFO becomes half full, i.e. 32 bytes.  (Tuneable with the DC
+  * register.)  Reading 32 bytes from the RX FIFO would normally require 8 bus
+  * accesses, whereas clearing it requires only 1 bus access.  So an 8-fold
+  * reduction in bus traffic and thus energy consumption is achieved.
+  *
+  * For *RX-only* transfers (tx_buf is %NULL), fill the TX FIFO by cyclically
+  * copying from the zero page.  The DMA descriptor to do this is preallocated
+  * in bcm2835_dma_init().  It must be terminated once the RX DMA channel is
+  * done and can then be reused.
+  *
+  * The BCM2835 DMA driver autodetects when a transaction copies from the zero
+  * page and utilizes the DMA controller's ability to synthesize zeroes instead
+  * of copying them from memory.  This reduces traffic on the memory bus.  The
+  * feature is not available on so-called "lite" channels, but normally TX DMA
+  * is backed by a full-featured channel.
+  *
+  * Zero-filling the TX FIFO is paced by the DREQ signal.  Unfortunately the
+  * BCM2835 SPI controller continues to assert DREQ even after the DLEN register
+  * has been counted down to zero (hardware erratum).  Thus, when the transfer
+  * has finished, the DMA engine zero-fills the TX FIFO until it is half full.
+  * (Tuneable with the DC register.)  So up to 9 gratuitous bus accesses are
+  * performed at the end of an RX-only transfer.
+  */
  static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr,
                                        struct spi_device *spi,
                                        struct spi_transfer *tfr,
                                        u32 cs)
  {
        struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
+       dma_cookie_t cookie;
        int ret;
  
        /* update usage statistics */
        bcm2835_spi_transfer_prologue(ctlr, tfr, bs, cs);
  
        /* setup tx-DMA */
-       ret = bcm2835_spi_prepare_sg(ctlr, tfr, true);
+       if (bs->tx_buf) {
+               ret = bcm2835_spi_prepare_sg(ctlr, spi, tfr, bs, true);
+       } else {
+               cookie = dmaengine_submit(bs->fill_tx_desc);
+               ret = dma_submit_error(cookie);
+       }
        if (ret)
                goto err_reset_hw;
  
-       /* start TX early */
-       dma_async_issue_pending(ctlr->dma_tx);
-       /* mark as dma pending */
-       bs->dma_pending = 1;
        /* set the DMA length */
        bcm2835_wr(bs, BCM2835_SPI_DLEN, bs->tx_len);
  
        bcm2835_wr(bs, BCM2835_SPI_CS,
                   cs | BCM2835_SPI_CS_TA | BCM2835_SPI_CS_DMAEN);
  
+       bs->tx_dma_active = true;
+       smp_wmb();
+       /* start TX early */
+       dma_async_issue_pending(ctlr->dma_tx);
        /* setup rx-DMA late - to run transfers while
         * mapping of the rx buffers still takes place
         * this saves 10us or more.
         */
-       ret = bcm2835_spi_prepare_sg(ctlr, tfr, false);
+       if (bs->rx_buf) {
+               ret = bcm2835_spi_prepare_sg(ctlr, spi, tfr, bs, false);
+       } else {
+               cookie = dmaengine_submit(bs->clear_rx_desc[spi->chip_select]);
+               ret = dma_submit_error(cookie);
+       }
        if (ret) {
                /* need to reset on errors */
                dmaengine_terminate_sync(ctlr->dma_tx);
-               bs->dma_pending = false;
+               bs->tx_dma_active = false;
                goto err_reset_hw;
        }
  
        /* start rx dma late */
        dma_async_issue_pending(ctlr->dma_rx);
+       bs->rx_dma_active = true;
+       smp_mb();
+       /*
+        * In case of a very short TX-only transfer, bcm2835_spi_dma_tx_done()
+        * may run before RX DMA is issued.  Terminate RX DMA if so.
+        */
+       if (!bs->rx_buf && !bs->tx_dma_active &&
+           cmpxchg(&bs->rx_dma_active, true, false)) {
+               dmaengine_terminate_async(ctlr->dma_rx);
+               bcm2835_spi_reset_hw(ctlr);
+       }
  
        /* wait for wakeup in framework */
        return 1;
@@@ -688,26 -839,52 +849,52 @@@ static bool bcm2835_spi_can_dma(struct 
        return true;
  }
  
- static void bcm2835_dma_release(struct spi_controller *ctlr)
+ static void bcm2835_dma_release(struct spi_controller *ctlr,
+                               struct bcm2835_spi *bs)
  {
+       int i;
        if (ctlr->dma_tx) {
                dmaengine_terminate_sync(ctlr->dma_tx);
+               if (bs->fill_tx_desc)
+                       dmaengine_desc_free(bs->fill_tx_desc);
+               if (bs->fill_tx_addr)
+                       dma_unmap_page_attrs(ctlr->dma_tx->device->dev,
+                                            bs->fill_tx_addr, sizeof(u32),
+                                            DMA_TO_DEVICE,
+                                            DMA_ATTR_SKIP_CPU_SYNC);
                dma_release_channel(ctlr->dma_tx);
                ctlr->dma_tx = NULL;
        }
        if (ctlr->dma_rx) {
                dmaengine_terminate_sync(ctlr->dma_rx);
+               for (i = 0; i < BCM2835_SPI_NUM_CS; i++)
+                       if (bs->clear_rx_desc[i])
+                               dmaengine_desc_free(bs->clear_rx_desc[i]);
+               if (bs->clear_rx_addr)
+                       dma_unmap_single(ctlr->dma_rx->device->dev,
+                                        bs->clear_rx_addr,
+                                        sizeof(bs->clear_rx_cs),
+                                        DMA_TO_DEVICE);
                dma_release_channel(ctlr->dma_rx);
                ctlr->dma_rx = NULL;
        }
  }
  
- static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev)
+ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev,
+                            struct bcm2835_spi *bs)
  {
        struct dma_slave_config slave_config;
        const __be32 *addr;
        dma_addr_t dma_reg_base;
-       int ret;
+       int ret, i;
  
        /* base address in dma-space */
        addr = of_get_address(ctlr->dev.of_node, 0, NULL, NULL);
                goto err_release;
        }
  
-       /* configure DMAs */
+       /*
+        * The TX DMA channel either copies a transfer's TX buffer to the FIFO
+        * or, in case of an RX-only transfer, cyclically copies from the zero
+        * page to the FIFO using a preallocated, reusable descriptor.
+        */
        slave_config.dst_addr = (u32)(dma_reg_base + BCM2835_SPI_FIFO);
        slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
  
        if (ret)
                goto err_config;
  
+       bs->fill_tx_addr = dma_map_page_attrs(ctlr->dma_tx->device->dev,
+                                             ZERO_PAGE(0), 0, sizeof(u32),
+                                             DMA_TO_DEVICE,
+                                             DMA_ATTR_SKIP_CPU_SYNC);
+       if (dma_mapping_error(ctlr->dma_tx->device->dev, bs->fill_tx_addr)) {
+               dev_err(dev, "cannot map zero page - not using DMA mode\n");
+               bs->fill_tx_addr = 0;
+               goto err_release;
+       }
+       bs->fill_tx_desc = dmaengine_prep_dma_cyclic(ctlr->dma_tx,
+                                                    bs->fill_tx_addr,
+                                                    sizeof(u32), 0,
+                                                    DMA_MEM_TO_DEV, 0);
+       if (!bs->fill_tx_desc) {
+               dev_err(dev, "cannot prepare fill_tx_desc - not using DMA mode\n");
+               goto err_release;
+       }
+       ret = dmaengine_desc_set_reuse(bs->fill_tx_desc);
+       if (ret) {
+               dev_err(dev, "cannot reuse fill_tx_desc - not using DMA mode\n");
+               goto err_release;
+       }
+       /*
+        * The RX DMA channel is used bidirectionally:  It either reads the
+        * RX FIFO or, in case of a TX-only transfer, cyclically writes a
+        * precalculated value to the CS register to clear the RX FIFO.
+        */
        slave_config.src_addr = (u32)(dma_reg_base + BCM2835_SPI_FIFO);
        slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       slave_config.dst_addr = (u32)(dma_reg_base + BCM2835_SPI_CS);
+       slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
  
        ret = dmaengine_slave_config(ctlr->dma_rx, &slave_config);
        if (ret)
                goto err_config;
  
+       bs->clear_rx_addr = dma_map_single(ctlr->dma_rx->device->dev,
+                                          bs->clear_rx_cs,
+                                          sizeof(bs->clear_rx_cs),
+                                          DMA_TO_DEVICE);
+       if (dma_mapping_error(ctlr->dma_rx->device->dev, bs->clear_rx_addr)) {
+               dev_err(dev, "cannot map clear_rx_cs - not using DMA mode\n");
+               bs->clear_rx_addr = 0;
+               goto err_release;
+       }
+       for (i = 0; i < BCM2835_SPI_NUM_CS; i++) {
+               bs->clear_rx_desc[i] = dmaengine_prep_dma_cyclic(ctlr->dma_rx,
+                                          bs->clear_rx_addr + i * sizeof(u32),
+                                          sizeof(u32), 0,
+                                          DMA_MEM_TO_DEV, 0);
+               if (!bs->clear_rx_desc[i]) {
+                       dev_err(dev, "cannot prepare clear_rx_desc - not using DMA mode\n");
+                       goto err_release;
+               }
+               ret = dmaengine_desc_set_reuse(bs->clear_rx_desc[i]);
+               if (ret) {
+                       dev_err(dev, "cannot reuse clear_rx_desc - not using DMA mode\n");
+                       goto err_release;
+               }
+       }
        /* all went well, so set can_dma */
        ctlr->can_dma = bcm2835_spi_can_dma;
-       /* need to do TX AND RX DMA, so we need dummy buffers */
-       ctlr->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;
  
        return;
  
@@@ -755,7 -993,7 +1003,7 @@@ err_config
        dev_err(dev, "issue configuring dma: %d - not using DMA mode\n",
                ret);
  err_release:
-       bcm2835_dma_release(ctlr);
+       bcm2835_dma_release(ctlr, bs);
  err:
        return;
  }
@@@ -822,7 -1060,7 +1070,7 @@@ static int bcm2835_spi_transfer_one(str
        struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
        unsigned long spi_hz, clk_hz, cdiv, spi_used_hz;
        unsigned long hz_per_byte, byte_limit;
-       u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+       u32 cs = bs->prepare_cs[spi->chip_select];
  
        /* set clock */
        spi_hz = tfr->speed_hz;
        bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
  
        /* handle all the 3-wire mode */
-       if (spi->mode & SPI_3WIRE && tfr->rx_buf &&
-           tfr->rx_buf != ctlr->dummy_rx)
+       if (spi->mode & SPI_3WIRE && tfr->rx_buf)
                cs |= BCM2835_SPI_CS_REN;
-       else
-               cs &= ~BCM2835_SPI_CS_REN;
-       /*
-        * The driver always uses software-controlled GPIO Chip Select.
-        * Set the hardware-controlled native Chip Select to an invalid
-        * value to prevent it from interfering.
-        */
-       cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01;
  
        /* set transmit buffers and length */
        bs->tx_buf = tfr->tx_buf;
@@@ -892,7 -1120,6 +1130,6 @@@ static int bcm2835_spi_prepare_message(
  {
        struct spi_device *spi = msg->spi;
        struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
-       u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
        int ret;
  
        if (ctlr->can_dma) {
                        return ret;
        }
  
-       cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA);
-       if (spi->mode & SPI_CPOL)
-               cs |= BCM2835_SPI_CS_CPOL;
-       if (spi->mode & SPI_CPHA)
-               cs |= BCM2835_SPI_CS_CPHA;
-       bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+       /*
+        * Set up clock polarity before spi_transfer_one_message() asserts
+        * chip select to avoid a gratuitous clock signal edge.
+        */
+       bcm2835_wr(bs, BCM2835_SPI_CS, bs->prepare_cs[spi->chip_select]);
  
        return 0;
  }
@@@ -925,11 -1149,12 +1159,12 @@@ static void bcm2835_spi_handle_err(stru
        struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
  
        /* if an error occurred and we have an active dma, then terminate */
-       if (cmpxchg(&bs->dma_pending, true, false)) {
-               dmaengine_terminate_sync(ctlr->dma_tx);
-               dmaengine_terminate_sync(ctlr->dma_rx);
-               bcm2835_spi_undo_prologue(bs);
-       }
+       dmaengine_terminate_sync(ctlr->dma_tx);
+       bs->tx_dma_active = false;
+       dmaengine_terminate_sync(ctlr->dma_rx);
+       bs->rx_dma_active = false;
+       bcm2835_spi_undo_prologue(bs);
        /* and reset */
        bcm2835_spi_reset_hw(ctlr);
  }
@@@ -941,14 -1166,50 +1176,50 @@@ static int chip_match_name(struct gpio_
  
  static int bcm2835_spi_setup(struct spi_device *spi)
  {
-       int err;
+       struct spi_controller *ctlr = spi->controller;
+       struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
        struct gpio_chip *chip;
+       enum gpio_lookup_flags lflags;
+       u32 cs;
+       /*
+        * Precalculate SPI slave's CS register value for ->prepare_message():
+        * The driver always uses software-controlled GPIO chip select, hence
+        * set the hardware-controlled native chip select to an invalid value
+        * to prevent it from interfering.
+        */
+       cs = BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01;
+       if (spi->mode & SPI_CPOL)
+               cs |= BCM2835_SPI_CS_CPOL;
+       if (spi->mode & SPI_CPHA)
+               cs |= BCM2835_SPI_CS_CPHA;
+       bs->prepare_cs[spi->chip_select] = cs;
+       /*
+        * Precalculate SPI slave's CS register value to clear RX FIFO
+        * in case of a TX-only DMA transfer.
+        */
+       if (ctlr->dma_rx) {
+               bs->clear_rx_cs[spi->chip_select] = cs |
+                                                   BCM2835_SPI_CS_TA |
+                                                   BCM2835_SPI_CS_DMAEN |
+                                                   BCM2835_SPI_CS_CLEAR_RX;
+               dma_sync_single_for_device(ctlr->dma_rx->device->dev,
+                                          bs->clear_rx_addr,
+                                          sizeof(bs->clear_rx_cs),
+                                          DMA_TO_DEVICE);
+       }
        /*
         * sanity checking the native-chipselects
         */
        if (spi->mode & SPI_NO_CS)
                return 0;
-       if (gpio_is_valid(spi->cs_gpio))
+       /*
+        * The SPI core has successfully requested the CS GPIO line from the
+        * device tree, so we are done.
+        */
+       if (spi->cs_gpiod)
                return 0;
        if (spi->chip_select > 1) {
                /* error in the case of native CS requested with CS > 1
                        "setup: only two native chip-selects are supported\n");
                return -EINVAL;
        }
-       /* now translate native cs to GPIO */
+       /*
+        * Translate native CS to GPIO
+        *
+        * FIXME: poking around in the gpiolib internals like this is
+        * not very good practice. Find a way to locate the real problem
+        * and fix it. Why is the GPIO descriptor in spi->cs_gpiod
+        * sometimes not assigned correctly? Erroneous device trees?
+        */
  
        /* get the gpio chip for the base */
        chip = gpiochip_find("pinctrl-bcm2835", chip_match_name);
        if (!chip)
                return 0;
  
-       /* and calculate the real CS */
-       spi->cs_gpio = chip->base + 8 - spi->chip_select;
+       /*
+        * Retrieve the corresponding GPIO line used for CS.
+        * The inversion semantics will be handled by the GPIO core
+        * code, so we pass GPIOS_OUT_LOW for "unasserted" and
+        * the correct flag for inversion semantics. The SPI_CS_HIGH
+        * on spi->mode cannot be checked for polarity in this case
+        * as the flag use_gpio_descriptors enforces SPI_CS_HIGH.
+        */
+       if (of_property_read_bool(spi->dev.of_node, "spi-cs-high"))
+               lflags = GPIO_ACTIVE_HIGH;
+       else
+               lflags = GPIO_ACTIVE_LOW;
+       spi->cs_gpiod = gpiochip_request_own_desc(chip, 8 - spi->chip_select,
+                                                 DRV_NAME,
+                                                 lflags,
+                                                 GPIOD_OUT_LOW);
+       if (IS_ERR(spi->cs_gpiod))
+               return PTR_ERR(spi->cs_gpiod);
  
        /* and set up the "mode" and level */
-       dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n",
-                spi->chip_select, spi->cs_gpio);
-       /* set up GPIO as output and pull to the correct level */
-       err = gpio_direction_output(spi->cs_gpio,
-                                   (spi->mode & SPI_CS_HIGH) ? 0 : 1);
-       if (err) {
-               dev_err(&spi->dev,
-                       "could not set CS%i gpio %i as output: %i",
-                       spi->chip_select, spi->cs_gpio, err);
-               return err;
-       }
+       dev_info(&spi->dev, "setting up native-CS%i to use GPIO\n",
+                spi->chip_select);
  
        return 0;
  }
@@@ -990,18 -1265,19 +1275,19 @@@ static int bcm2835_spi_probe(struct pla
  {
        struct spi_controller *ctlr;
        struct bcm2835_spi *bs;
-       struct resource *res;
        int err;
  
-       ctlr = spi_alloc_master(&pdev->dev, sizeof(*bs));
+       ctlr = spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs),
+                                                 dma_get_cache_alignment()));
        if (!ctlr)
                return -ENOMEM;
  
        platform_set_drvdata(pdev, ctlr);
  
+       ctlr->use_gpio_descriptors = true;
        ctlr->mode_bits = BCM2835_SPI_MODE_BITS;
        ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
-       ctlr->num_chipselect = 3;
+       ctlr->num_chipselect = BCM2835_SPI_NUM_CS;
        ctlr->setup = bcm2835_spi_setup;
        ctlr->transfer_one = bcm2835_spi_transfer_one;
        ctlr->handle_err = bcm2835_spi_handle_err;
  
        bs = spi_controller_get_devdata(ctlr);
  
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       bs->regs = devm_ioremap_resource(&pdev->dev, res);
+       bs->regs = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(bs->regs)) {
                err = PTR_ERR(bs->regs);
                goto out_controller_put;
  
        bs->irq = platform_get_irq(pdev, 0);
        if (bs->irq <= 0) {
-               dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq);
                err = bs->irq ? bs->irq : -ENODEV;
                goto out_controller_put;
        }
  
        clk_prepare_enable(bs->clk);
  
-       bcm2835_dma_init(ctlr, &pdev->dev);
+       bcm2835_dma_init(ctlr, &pdev->dev, bs);
  
        /* initialise the hardware with the default polarities */
        bcm2835_wr(bs, BCM2835_SPI_CS,
@@@ -1077,7 -1351,7 +1361,7 @@@ static int bcm2835_spi_remove(struct pl
  
        clk_disable_unprepare(bs->clk);
  
-       bcm2835_dma_release(ctlr);
+       bcm2835_dma_release(ctlr, bs);
  
        return 0;
  }
diff --combined drivers/spi/spi-dw-pci.c
index 90e7b789da3b07ee134333468a2ac782ff2ca87f,4e3a4c317636a15ae7e0a8e379d47c152de08a91..140644913e6c5c4aafa1d56c3f5a2a1abf249d3a
@@@ -106,16 -106,14 +106,14 @@@ static void spi_pci_remove(struct pci_d
  #ifdef CONFIG_PM_SLEEP
  static int spi_suspend(struct device *dev)
  {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct dw_spi *dws = pci_get_drvdata(pdev);
+       struct dw_spi *dws = dev_get_drvdata(dev);
  
        return dw_spi_suspend_host(dws);
  }
  
  static int spi_resume(struct device *dev)
  {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct dw_spi *dws = pci_get_drvdata(pdev);
+       struct dw_spi *dws = dev_get_drvdata(dev);
  
        return dw_spi_resume_host(dws);
  }
@@@ -140,7 -138,6 +138,7 @@@ static const struct pci_device_id pci_i
        { PCI_VDEVICE(INTEL, 0x4b87), (kernel_ulong_t)&spi_pci_ehl_desc},
        {},
  };
 +MODULE_DEVICE_TABLE(pci, pci_ids);
  
  static struct pci_driver dw_spi_driver = {
        .name =         DRIVER_NAME,
index 4e99a0f25c298874f353f555f4a2143edf0b510d,d4453177ad4a8a73ebb40f17cccdde036cce814b..47cde1864630e02b5e3c8d253bb636c698cebdb9
@@@ -7,6 -7,7 +7,7 @@@
  #include <linux/bitfield.h>
  #include <linux/bitops.h>
  #include <linux/clk.h>
+ #include <linux/delay.h>
  #include <linux/interrupt.h>
  #include <linux/io.h>
  #include <linux/module.h>
@@@ -16,6 -17,7 +17,7 @@@
  #include <asm/unaligned.h>
  
  #define SSI_TIMEOUT_MS                2000
+ #define SSI_POLL_TIMEOUT_US   200
  #define SSI_MAX_CLK_DIVIDER   254
  #define SSI_MIN_CLK_DIVIDER   4
  
@@@ -214,7 -216,6 +216,7 @@@ static void uniphier_spi_setup_transfer
        if (!priv->is_save_param || priv->mode != spi->mode) {
                uniphier_spi_set_mode(spi);
                priv->mode = spi->mode;
 +              priv->is_save_param = false;
        }
  
        if (!priv->is_save_param || priv->bits_per_word != t->bits_per_word) {
                priv->speed_hz = t->speed_hz;
        }
  
-       if (!priv->is_save_param)
-               priv->is_save_param = true;
+       priv->is_save_param = true;
  
        /* reset FIFOs */
        val = SSI_FC_TXFFL | SSI_FC_RXFFL;
@@@ -291,21 -291,23 +292,23 @@@ static void uniphier_spi_recv(struct un
  
  static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv)
  {
-       unsigned int tx_count;
+       unsigned int fifo_threshold, fill_bytes;
        u32 val;
  
-       tx_count = DIV_ROUND_UP(priv->tx_bytes,
+       fifo_threshold = DIV_ROUND_UP(priv->rx_bytes,
                                bytes_per_word(priv->bits_per_word));
-       tx_count = min(tx_count, SSI_FIFO_DEPTH);
+       fifo_threshold = min(fifo_threshold, SSI_FIFO_DEPTH);
+       fill_bytes = fifo_threshold - (priv->rx_bytes - priv->tx_bytes);
  
        /* set fifo threshold */
        val = readl(priv->base + SSI_FC);
        val &= ~(SSI_FC_TXFTH_MASK | SSI_FC_RXFTH_MASK);
-       val |= FIELD_PREP(SSI_FC_TXFTH_MASK, tx_count);
-       val |= FIELD_PREP(SSI_FC_RXFTH_MASK, tx_count);
+       val |= FIELD_PREP(SSI_FC_TXFTH_MASK, fifo_threshold);
+       val |= FIELD_PREP(SSI_FC_RXFTH_MASK, fifo_threshold);
        writel(val, priv->base + SSI_FC);
  
-       while (tx_count--)
+       while (fill_bytes--)
                uniphier_spi_send(priv);
  }
  
@@@ -324,20 -326,14 +327,14 @@@ static void uniphier_spi_set_cs(struct 
        writel(val, priv->base + SSI_FPS);
  }
  
- static int uniphier_spi_transfer_one(struct spi_master *master,
-                                    struct spi_device *spi,
-                                    struct spi_transfer *t)
+ static int uniphier_spi_transfer_one_irq(struct spi_master *master,
+                                        struct spi_device *spi,
+                                        struct spi_transfer *t)
  {
        struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
        struct device *dev = master->dev.parent;
        unsigned long time_left;
  
-       /* Terminate and return success for 0 byte length transfer */
-       if (!t->len)
-               return 0;
-       uniphier_spi_setup_transfer(spi, t);
        reinit_completion(&priv->xfer_done);
  
        uniphier_spi_fill_tx_fifo(priv);
        return priv->error;
  }
  
+ static int uniphier_spi_transfer_one_poll(struct spi_master *master,
+                                         struct spi_device *spi,
+                                         struct spi_transfer *t)
+ {
+       struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
+       int loop = SSI_POLL_TIMEOUT_US * 10;
+       while (priv->tx_bytes) {
+               uniphier_spi_fill_tx_fifo(priv);
+               while ((priv->rx_bytes - priv->tx_bytes) > 0) {
+                       while (!(readl(priv->base + SSI_SR) & SSI_SR_RNE)
+                                                               && loop--)
+                               ndelay(100);
+                       if (loop == -1)
+                               goto irq_transfer;
+                       uniphier_spi_recv(priv);
+               }
+       }
+       return 0;
+ irq_transfer:
+       return uniphier_spi_transfer_one_irq(master, spi, t);
+ }
+ static int uniphier_spi_transfer_one(struct spi_master *master,
+                                    struct spi_device *spi,
+                                    struct spi_transfer *t)
+ {
+       struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
+       unsigned long threshold;
+       /* Terminate and return success for 0 byte length transfer */
+       if (!t->len)
+               return 0;
+       uniphier_spi_setup_transfer(spi, t);
+       /*
+        * If the transfer operation will take longer than
+        * SSI_POLL_TIMEOUT_US, it should use irq.
+        */
+       threshold = DIV_ROUND_UP(SSI_POLL_TIMEOUT_US * priv->speed_hz,
+                                       USEC_PER_SEC * BITS_PER_BYTE);
+       if (t->len > threshold)
+               return uniphier_spi_transfer_one_irq(master, spi, t);
+       else
+               return uniphier_spi_transfer_one_poll(master, spi, t);
+ }
  static int uniphier_spi_prepare_transfer_hardware(struct spi_master *master)
  {
        struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
@@@ -420,7 -469,6 +470,6 @@@ static int uniphier_spi_probe(struct pl
  {
        struct uniphier_spi_priv *priv;
        struct spi_master *master;
-       struct resource *res;
        unsigned long clk_rate;
        int irq;
        int ret;
        priv->master = master;
        priv->is_save_param = false;
  
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       priv->base = devm_ioremap_resource(&pdev->dev, res);
+       priv->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(priv->base)) {
                ret = PTR_ERR(priv->base);
                goto out_master_put;
  
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
-               dev_err(&pdev->dev, "failed to get IRQ\n");
                ret = irq;
                goto out_disable_clk;
        }