spi: davinci: add comment about dummy tx buffer usage
[sfrench/cifs-2.6.git] / drivers / spi / spi-davinci.c
index 02fb96797ac8b9ec52f41c8a13f93b290db0fc1c..595acdcfc7d0832fbe7ef1b232e039b005788541 100644 (file)
 #define SPIDEF         0x4c
 #define SPIFMT0                0x50
 
+#define DMA_MIN_BYTES  16
+
 /* SPI Controller driver's private data. */
 struct davinci_spi {
        struct spi_bitbang      bitbang;
@@ -389,6 +391,7 @@ static int davinci_spi_of_setup(struct spi_device *spi)
 {
        struct davinci_spi_config *spicfg = spi->controller_data;
        struct device_node *np = spi->dev.of_node;
+       struct davinci_spi *dspi = spi_master_get_devdata(spi->master);
        u32 prop;
 
        if (spicfg == NULL && np) {
@@ -400,6 +403,9 @@ static int davinci_spi_of_setup(struct spi_device *spi)
                if (!of_property_read_u32(np, "ti,spi-wdelay", &prop))
                        spicfg->wdelay = (u8)prop;
                spi->controller_data = spicfg;
+
+               if (dspi->dma_rx && dspi->dma_tx)
+                       spicfg->io_type = SPI_IO_TYPE_DMA;
        }
 
        return 0;
@@ -467,6 +473,22 @@ static void davinci_spi_cleanup(struct spi_device *spi)
                kfree(spicfg);
 }
 
+static bool davinci_spi_can_dma(struct spi_master *master,
+                               struct spi_device *spi,
+                               struct spi_transfer *xfer)
+{
+       struct davinci_spi_config *spicfg = spi->controller_data;
+       bool can_dma = false;
+
+       if (spicfg)
+               can_dma = (spicfg->io_type == SPI_IO_TYPE_DMA) &&
+                       (xfer->len >= DMA_MIN_BYTES) &&
+                       !is_vmalloc_addr(xfer->rx_buf) &&
+                       !is_vmalloc_addr(xfer->tx_buf);
+
+       return can_dma;
+}
+
 static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status)
 {
        struct device *sdev = dspi->bitbang.master->dev.parent;
@@ -581,8 +603,6 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
        struct davinci_spi_config *spicfg;
        struct davinci_spi_platform_data *pdata;
        unsigned uninitialized_var(rx_buf_count);
-       void *dummy_buf = NULL;
-       struct scatterlist sg_rx, sg_tx;
 
        dspi = spi_master_get_devdata(spi->master);
        pdata = &dspi->pdata;
@@ -605,10 +625,9 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
 
        reinit_completion(&dspi->done);
 
-       if (spicfg->io_type == SPI_IO_TYPE_INTR)
-               set_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
-
-       if (spicfg->io_type != SPI_IO_TYPE_DMA) {
+       if (!davinci_spi_can_dma(spi->master, spi, t)) {
+               if (spicfg->io_type != SPI_IO_TYPE_POLL)
+                       set_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
                /* start the transfer */
                dspi->wcount--;
                tx_data = dspi->get_tx(dspi);
@@ -630,51 +649,28 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
                };
                struct dma_async_tx_descriptor *rxdesc;
                struct dma_async_tx_descriptor *txdesc;
-               void *buf;
-
-               dummy_buf = kzalloc(t->len, GFP_KERNEL);
-               if (!dummy_buf)
-                       goto err_alloc_dummy_buf;
 
                dmaengine_slave_config(dspi->dma_rx, &dma_rx_conf);
                dmaengine_slave_config(dspi->dma_tx, &dma_tx_conf);
 
-               sg_init_table(&sg_rx, 1);
-               if (!t->rx_buf)
-                       buf = dummy_buf;
-               else
-                       buf = t->rx_buf;
-               t->rx_dma = dma_map_single(&spi->dev, buf,
-                               t->len, DMA_FROM_DEVICE);
-               if (dma_mapping_error(&spi->dev, !t->rx_dma)) {
-                       ret = -EFAULT;
-                       goto err_rx_map;
-               }
-               sg_dma_address(&sg_rx) = t->rx_dma;
-               sg_dma_len(&sg_rx) = t->len;
-
-               sg_init_table(&sg_tx, 1);
-               if (!t->tx_buf)
-                       buf = dummy_buf;
-               else
-                       buf = (void *)t->tx_buf;
-               t->tx_dma = dma_map_single(&spi->dev, buf,
-                               t->len, DMA_TO_DEVICE);
-               if (dma_mapping_error(&spi->dev, t->tx_dma)) {
-                       ret = -EFAULT;
-                       goto err_tx_map;
-               }
-               sg_dma_address(&sg_tx) = t->tx_dma;
-               sg_dma_len(&sg_tx) = t->len;
-
                rxdesc = dmaengine_prep_slave_sg(dspi->dma_rx,
-                               &sg_rx, 1, DMA_DEV_TO_MEM,
+                               t->rx_sg.sgl, t->rx_sg.nents, DMA_DEV_TO_MEM,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
                if (!rxdesc)
                        goto err_desc;
 
+               if (!t->tx_buf) {
+                       /* To avoid errors when doing rx-only transfers with
+                        * many SG entries (> 20), use the rx buffer as the
+                        * dummy tx buffer so that dma reloads are done at the
+                        * same time for rx and tx.
+                        */
+                       t->tx_sg.sgl = t->rx_sg.sgl;
+                       t->tx_sg.nents = t->rx_sg.nents;
+               }
+
                txdesc = dmaengine_prep_slave_sg(dspi->dma_tx,
-                               &sg_tx, 1, DMA_MEM_TO_DEV,
+                               t->tx_sg.sgl, t->tx_sg.nents, DMA_MEM_TO_DEV,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
                if (!txdesc)
                        goto err_desc;
@@ -710,16 +706,9 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
        }
 
        clear_io_bits(dspi->base + SPIINT, SPIINT_MASKALL);
-       if (spicfg->io_type == SPI_IO_TYPE_DMA) {
+       if (davinci_spi_can_dma(spi->master, spi, t))
                clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
 
-               dma_unmap_single(&spi->dev, t->rx_dma,
-                               t->len, DMA_FROM_DEVICE);
-               dma_unmap_single(&spi->dev, t->tx_dma,
-                               t->len, DMA_TO_DEVICE);
-               kfree(dummy_buf);
-       }
-
        clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
        set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
 
@@ -742,12 +731,6 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
        return t->len;
 
 err_desc:
-       dma_unmap_single(&spi->dev, t->tx_dma, t->len, DMA_TO_DEVICE);
-err_tx_map:
-       dma_unmap_single(&spi->dev, t->rx_dma, t->len, DMA_FROM_DEVICE);
-err_rx_map:
-       kfree(dummy_buf);
-err_alloc_dummy_buf:
        return ret;
 }
 
@@ -988,8 +971,10 @@ static int davinci_spi_probe(struct platform_device *pdev)
        master->bus_num = pdev->id;
        master->num_chipselect = pdata->num_chipselect;
        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16);
+       master->flags = SPI_MASTER_MUST_RX;
        master->setup = davinci_spi_setup;
        master->cleanup = davinci_spi_cleanup;
+       master->can_dma = davinci_spi_can_dma;
 
        dspi->bitbang.chipselect = davinci_spi_chipselect;
        dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;