aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Niebuhr <bniebuhr@efjohnson.com>2010-09-28 04:29:26 -0400
committerSekhar Nori <nsekhar@ti.com>2010-11-18 08:08:33 -0500
commitc29e3c60e75d1cc1262ac8af379738b6fd851f33 (patch)
tree19697ab9c0a16e8152f31825ddb8a413ef3b1b72
parent96fd881f22b44fc14772316a6b9231012393cda8 (diff)
spi: davinci: always start transmit DMA
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>
-rw-r--r--arch/arm/mach-davinci/dm355.c1
-rw-r--r--arch/arm/mach-davinci/include/mach/spi.h1
-rw-r--r--drivers/spi/davinci_spi.c22
3 files changed, 11 insertions, 13 deletions
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index e311f29ffb57..27ee870b2d27 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -413,6 +413,7 @@ static struct davinci_spi_platform_data dm355_spi0_pdata = {
413 .version = SPI_VERSION_1, 413 .version = SPI_VERSION_1,
414 .num_chipselect = 2, 414 .num_chipselect = 2,
415 .clk_internal = 1, 415 .clk_internal = 1,
416 .cshold_bug = true,
416}; 417};
417static struct platform_device dm355_spi0_device = { 418static struct platform_device dm355_spi0_device = {
418 .name = "spi_davinci", 419 .name = "spi_davinci",
diff --git a/arch/arm/mach-davinci/include/mach/spi.h b/arch/arm/mach-davinci/include/mach/spi.h
index ab45b89a0c5f..68db6d5daaf4 100644
--- a/arch/arm/mach-davinci/include/mach/spi.h
+++ b/arch/arm/mach-davinci/include/mach/spi.h
@@ -33,6 +33,7 @@ struct davinci_spi_platform_data {
33 u8 intr_line; 33 u8 intr_line;
34 u8 use_dma; 34 u8 use_dma;
35 u8 *chip_sel; 35 u8 *chip_sel;
36 bool cshold_bug;
36}; 37};
37 38
38struct davinci_spi_config { 39struct davinci_spi_config {
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index 4aa522134a90..a5f03dd8d8da 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -719,13 +719,14 @@ static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t)
719 struct davinci_spi *davinci_spi; 719 struct davinci_spi *davinci_spi;
720 int int_status = 0; 720 int int_status = 0;
721 int count, temp_count; 721 int count, temp_count;
722 u32 data1_reg_val;
723 struct davinci_spi_dma *davinci_spi_dma; 722 struct davinci_spi_dma *davinci_spi_dma;
724 int data_type, ret; 723 int data_type, ret;
725 unsigned long tx_reg, rx_reg; 724 unsigned long tx_reg, rx_reg;
725 struct davinci_spi_platform_data *pdata;
726 struct device *sdev; 726 struct device *sdev;
727 727
728 davinci_spi = spi_master_get_devdata(spi->master); 728 davinci_spi = spi_master_get_devdata(spi->master);
729 pdata = davinci_spi->pdata;
729 sdev = davinci_spi->bitbang.master->dev.parent; 730 sdev = davinci_spi->bitbang.master->dev.parent;
730 731
731 davinci_spi_dma = &davinci_spi->dma_channels; 732 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)
739 /* convert len to words based on bits_per_word */ 740 /* convert len to words based on bits_per_word */
740 data_type = davinci_spi->bytes_per_word[spi->chip_select]; 741 data_type = davinci_spi->bytes_per_word[spi->chip_select];
741 742
742 data1_reg_val = ioread32(davinci_spi->base + SPIDAT1);
743
744 init_completion(&davinci_spi_dma->dma_rx_completion); 743 init_completion(&davinci_spi_dma->dma_rx_completion);
745 init_completion(&davinci_spi_dma->dma_tx_completion); 744 init_completion(&davinci_spi_dma->dma_tx_completion);
746 745
@@ -781,9 +780,6 @@ static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t)
781 edma_set_dest_index(davinci_spi_dma->dma_tx_channel, 0, 0); 780 edma_set_dest_index(davinci_spi_dma->dma_tx_channel, 0, 0);
782 781
783 if (t->rx_buf) { 782 if (t->rx_buf) {
784 /* initiate transaction */
785 iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1);
786
787 t->rx_dma = dma_map_single(&spi->dev, (void *)t->rx_buf, count, 783 t->rx_dma = dma_map_single(&spi->dev, (void *)t->rx_buf, count,
788 DMA_FROM_DEVICE); 784 DMA_FROM_DEVICE);
789 if (dma_mapping_error(&spi->dev, t->rx_dma)) { 785 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)
805 data_type, 0); 801 data_type, 0);
806 } 802 }
807 803
808 if ((t->tx_buf) || (t->rx_buf)) 804 if (pdata->cshold_bug) {
809 edma_start(davinci_spi_dma->dma_tx_channel); 805 u16 spidat1 = ioread16(davinci_spi->base + SPIDAT1 + 2);
806 iowrite16(spidat1, davinci_spi->base + SPIDAT1 + 2);
807 }
810 808
811 if (t->rx_buf) 809 if (t->rx_buf)
812 edma_start(davinci_spi_dma->dma_rx_channel); 810 edma_start(davinci_spi_dma->dma_rx_channel);
813 811
814 if ((t->rx_buf) || (t->tx_buf)) 812 edma_start(davinci_spi_dma->dma_tx_channel);
815 davinci_spi_set_dma_req(spi, 1); 813 davinci_spi_set_dma_req(spi, 1);
816 814
817 if (t->tx_buf) 815 wait_for_completion_interruptible(&davinci_spi_dma->dma_tx_completion);
818 wait_for_completion_interruptible(
819 &davinci_spi_dma->dma_tx_completion);
820 816
821 if (t->rx_buf) 817 if (t->rx_buf)
822 wait_for_completion_interruptible( 818 wait_for_completion_interruptible(