]> git.openfabrics.org - ~emulex/infiniband.git/commitdiff
spi: davinci: always start transmit DMA
authorBrian Niebuhr <bniebuhr@efjohnson.com>
Tue, 28 Sep 2010 08:29:26 +0000 (13:59 +0530)
committerSekhar Nori <nsekhar@ti.com>
Thu, 18 Nov 2010 13:08:33 +0000 (18:38 +0530)
Due to the full duplex nature of the SPI bus, the SPI master
on DaVinci needs transmit to be active even if the tranfer is
only meant to collect receive data.

The current code achieves this by using a temporary zeroed buffer
to provide DMA data in case the transfer does not have a transmit
buffer provided.

However, the transmit DMA is started only if transmit buffer is
provided rendering the temporary buffer unused. Instead the code
relies on a write to SPIDAT1 register to trigger transmit operation.
This however only sends two bytes of data.

Fix this by starting transmit DMA always.

This changes exposes a bug on DM355 where the CSHOLD bit in
SPIDAT1 needs to be written to in between transfers. Handle
that by introducing a "cshold_bug" platform data which is
set to true for DM355.

Signed-off-by: Brian Niebuhr <bniebuhr@efjohnson.com>
Tested-By: Michael Williamson <michael.williamson@criticallink.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/include/mach/spi.h
drivers/spi/davinci_spi.c

index e311f29ffb5798d28e6e4f9382f255337e12579b..27ee870b2d27f9a324bd5b9f575f6ec1f813065d 100644 (file)
@@ -413,6 +413,7 @@ static struct davinci_spi_platform_data dm355_spi0_pdata = {
        .version        = SPI_VERSION_1,
        .num_chipselect = 2,
        .clk_internal   = 1,
+       .cshold_bug     = true,
 };
 static struct platform_device dm355_spi0_device = {
        .name = "spi_davinci",
index ab45b89a0c5f047de847539696e1c75e64597c42..68db6d5daaf46125ff978b020ebf352ac24075f1 100644 (file)
@@ -33,6 +33,7 @@ struct davinci_spi_platform_data {
        u8      intr_line;
        u8      use_dma;
        u8      *chip_sel;
+       bool    cshold_bug;
 };
 
 struct davinci_spi_config {
index 4aa522134a90b4331329405db194c466369437f0..a5f03dd8d8da48571cd78d63fbab5ac425a3d24a 100644 (file)
@@ -719,13 +719,14 @@ static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t)
        struct davinci_spi *davinci_spi;
        int int_status = 0;
        int count, temp_count;
-       u32 data1_reg_val;
        struct davinci_spi_dma *davinci_spi_dma;
        int data_type, ret;
        unsigned long tx_reg, rx_reg;
+       struct davinci_spi_platform_data *pdata;
        struct device *sdev;
 
        davinci_spi = spi_master_get_devdata(spi->master);
+       pdata = davinci_spi->pdata;
        sdev = davinci_spi->bitbang.master->dev.parent;
 
        davinci_spi_dma = &davinci_spi->dma_channels;
@@ -739,8 +740,6 @@ static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t)
        /* convert len to words based on bits_per_word */
        data_type = davinci_spi->bytes_per_word[spi->chip_select];
 
-       data1_reg_val = ioread32(davinci_spi->base + SPIDAT1);
-
        init_completion(&davinci_spi_dma->dma_rx_completion);
        init_completion(&davinci_spi_dma->dma_tx_completion);
 
@@ -781,9 +780,6 @@ static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t)
        edma_set_dest_index(davinci_spi_dma->dma_tx_channel, 0, 0);
 
        if (t->rx_buf) {
-               /* initiate transaction */
-               iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1);
-
                t->rx_dma = dma_map_single(&spi->dev, (void *)t->rx_buf, count,
                                DMA_FROM_DEVICE);
                if (dma_mapping_error(&spi->dev, t->rx_dma)) {
@@ -805,18 +801,18 @@ static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t)
                                data_type, 0);
        }
 
-       if ((t->tx_buf) || (t->rx_buf))
-               edma_start(davinci_spi_dma->dma_tx_channel);
+       if (pdata->cshold_bug) {
+               u16 spidat1 = ioread16(davinci_spi->base + SPIDAT1 + 2);
+               iowrite16(spidat1, davinci_spi->base + SPIDAT1 + 2);
+       }
 
        if (t->rx_buf)
                edma_start(davinci_spi_dma->dma_rx_channel);
 
-       if ((t->rx_buf) || (t->tx_buf))
-               davinci_spi_set_dma_req(spi, 1);
+       edma_start(davinci_spi_dma->dma_tx_channel);
+       davinci_spi_set_dma_req(spi, 1);
 
-       if (t->tx_buf)
-               wait_for_completion_interruptible(
-                               &davinci_spi_dma->dma_tx_completion);
+       wait_for_completion_interruptible(&davinci_spi_dma->dma_tx_completion);
 
        if (t->rx_buf)
                wait_for_completion_interruptible(