summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-davinci/include/mach/spi.h1
-rw-r--r--drivers/spi/davinci_spi.c153
2 files changed, 51 insertions, 103 deletions
diff --git a/arch/arm/mach-davinci/include/mach/spi.h b/arch/arm/mach-davinci/include/mach/spi.h
index 68db6d5..f7586a0 100644
--- a/arch/arm/mach-davinci/include/mach/spi.h
+++ b/arch/arm/mach-davinci/include/mach/spi.h
@@ -31,7 +31,6 @@ struct davinci_spi_platform_data {
u8 num_chipselect;
u8 clk_internal;
u8 intr_line;
- u8 use_dma;
u8 *chip_sel;
bool cshold_bug;
};
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index 9695f98..6db4786 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -116,8 +116,6 @@
struct davinci_spi_dma {
int dma_tx_channel;
int dma_rx_channel;
- int dma_tx_sync_dev;
- int dma_rx_sync_dev;
enum dma_event_q eventq;
struct completion dma_tx_completion;
@@ -153,8 +151,6 @@ struct davinci_spi {
static struct davinci_spi_config davinci_spi_default_cfg;
-static unsigned use_dma;
-
static void davinci_spi_rx_buf_u8(u32 data, struct davinci_spi *davinci_spi)
{
if (davinci_spi->rx) {
@@ -391,12 +387,7 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
static void davinci_spi_dma_rx_callback(unsigned lch, u16 ch_status, void *data)
{
- struct spi_device *spi = (struct spi_device *)data;
- struct davinci_spi *davinci_spi;
- struct davinci_spi_dma *davinci_spi_dma;
-
- davinci_spi = spi_master_get_devdata(spi->master);
- davinci_spi_dma = &davinci_spi->dma_channels;
+ struct davinci_spi_dma *davinci_spi_dma = data;
if (ch_status == DMA_COMPLETE)
edma_stop(davinci_spi_dma->dma_rx_channel);
@@ -408,12 +399,7 @@ static void davinci_spi_dma_rx_callback(unsigned lch, u16 ch_status, void *data)
static void davinci_spi_dma_tx_callback(unsigned lch, u16 ch_status, void *data)
{
- struct spi_device *spi = (struct spi_device *)data;
- struct davinci_spi *davinci_spi;
- struct davinci_spi_dma *davinci_spi_dma;
-
- davinci_spi = spi_master_get_devdata(spi->master);
- davinci_spi_dma = &davinci_spi->dma_channels;
+ struct davinci_spi_dma *davinci_spi_dma = data;
if (ch_status == DMA_COMPLETE)
edma_stop(davinci_spi_dma->dma_tx_channel);
@@ -423,39 +409,6 @@ static void davinci_spi_dma_tx_callback(unsigned lch, u16 ch_status, void *data)
complete(&davinci_spi_dma->dma_tx_completion);
}
-static int davinci_spi_request_dma(struct spi_device *spi)
-{
- struct davinci_spi *davinci_spi;
- struct davinci_spi_dma *davinci_spi_dma;
- struct device *sdev;
- int r;
-
- davinci_spi = spi_master_get_devdata(spi->master);
- davinci_spi_dma = &davinci_spi->dma_channels;
- sdev = davinci_spi->bitbang.master->dev.parent;
-
- r = edma_alloc_channel(davinci_spi_dma->dma_rx_sync_dev,
- davinci_spi_dma_rx_callback, spi,
- davinci_spi_dma->eventq);
- if (r < 0) {
- dev_dbg(sdev, "Unable to request DMA channel for SPI RX\n");
- return -EAGAIN;
- }
- davinci_spi_dma->dma_rx_channel = r;
- r = edma_alloc_channel(davinci_spi_dma->dma_tx_sync_dev,
- davinci_spi_dma_tx_callback, spi,
- davinci_spi_dma->eventq);
- if (r < 0) {
- edma_free_channel(davinci_spi_dma->dma_rx_channel);
- davinci_spi_dma->dma_rx_channel = -1;
- dev_dbg(sdev, "Unable to request DMA channel for SPI TX\n");
- return -EAGAIN;
- }
- davinci_spi_dma->dma_tx_channel = r;
-
- return 0;
-}
-
/**
* davinci_spi_setup - This functions will set default transfer method
* @spi: spi device on which data transfer to be done
@@ -466,7 +419,6 @@ static int davinci_spi_setup(struct spi_device *spi)
{
int retval = 0;
struct davinci_spi *davinci_spi;
- struct davinci_spi_dma *davinci_spi_dma;
struct davinci_spi_platform_data *pdata;
davinci_spi = spi_master_get_devdata(spi->master);
@@ -494,33 +446,9 @@ static int davinci_spi_setup(struct spi_device *spi)
clear_io_bits(davinci_spi->base + SPIGCR1,
SPIGCR1_LOOPBACK_MASK);
- if (use_dma) {
- davinci_spi_dma = &davinci_spi->dma_channels;
-
- if ((davinci_spi_dma->dma_rx_channel == -1) ||
- (davinci_spi_dma->dma_tx_channel == -1))
- retval = davinci_spi_request_dma(spi);
- }
-
return retval;
}
-static void davinci_spi_cleanup(struct spi_device *spi)
-{
- if (use_dma) {
- struct davinci_spi *davinci_spi =
- spi_master_get_devdata(spi->master);
- struct davinci_spi_dma *davinci_spi_dma =
- &davinci_spi->dma_channels;
-
- if ((davinci_spi_dma->dma_rx_channel != -1)
- && (davinci_spi_dma->dma_tx_channel != -1)) {
- edma_free_channel(davinci_spi_dma->dma_tx_channel);
- edma_free_channel(davinci_spi_dma->dma_rx_channel);
- }
- }
-}
-
static int davinci_spi_check_error(struct davinci_spi *davinci_spi,
int int_status)
{
@@ -842,6 +770,30 @@ static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t)
return t->len;
}
+static int davinci_spi_request_dma(struct davinci_spi_dma *davinci_spi_dma)
+{
+ int r;
+
+ r = edma_alloc_channel(davinci_spi_dma->dma_rx_channel,
+ davinci_spi_dma_rx_callback, davinci_spi_dma,
+ davinci_spi_dma->eventq);
+ if (r < 0) {
+ pr_err("Unable to request DMA channel for SPI RX\n");
+ return -EAGAIN;
+ }
+
+ r = edma_alloc_channel(davinci_spi_dma->dma_tx_channel,
+ davinci_spi_dma_tx_callback, davinci_spi_dma,
+ davinci_spi_dma->eventq);
+ if (r < 0) {
+ edma_free_channel(davinci_spi_dma->dma_rx_channel);
+ pr_err("Unable to request DMA channel for SPI TX\n");
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
/**
* davinci_spi_probe - probe function for SPI Master Controller
* @pdev: platform_device structure which contains plateform specific data
@@ -928,45 +880,39 @@ static int davinci_spi_probe(struct platform_device *pdev)
master->bus_num = pdev->id;
master->num_chipselect = pdata->num_chipselect;
master->setup = davinci_spi_setup;
- master->cleanup = davinci_spi_cleanup;
davinci_spi->bitbang.chipselect = davinci_spi_chipselect;
davinci_spi->bitbang.setup_transfer = davinci_spi_setup_transfer;
davinci_spi->version = pdata->version;
- use_dma = pdata->use_dma;
davinci_spi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP;
if (davinci_spi->version == SPI_VERSION_2)
davinci_spi->bitbang.flags |= SPI_READY;
- if (use_dma) {
- r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (r)
- dma_rx_chan = r->start;
- r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (r)
- dma_tx_chan = r->start;
- r = platform_get_resource(pdev, IORESOURCE_DMA, 2);
- if (r)
- dma_eventq = r->start;
- }
-
- if (!use_dma ||
- dma_rx_chan == SPI_NO_RESOURCE ||
- dma_tx_chan == SPI_NO_RESOURCE ||
- dma_eventq == SPI_NO_RESOURCE) {
- davinci_spi->bitbang.txrx_bufs = davinci_spi_bufs_pio;
- use_dma = 0;
- } else {
- davinci_spi->bitbang.txrx_bufs = davinci_spi_bufs_dma;
-
- davinci_spi->dma_channels.dma_rx_channel = -1;
- davinci_spi->dma_channels.dma_rx_sync_dev = dma_rx_chan;
- davinci_spi->dma_channels.dma_tx_channel = -1;
- davinci_spi->dma_channels.dma_tx_sync_dev = dma_tx_chan;
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (r)
+ dma_rx_chan = r->start;
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (r)
+ dma_tx_chan = r->start;
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 2);
+ if (r)
+ dma_eventq = r->start;
+
+ davinci_spi->bitbang.txrx_bufs = davinci_spi_bufs_pio;
+ if (dma_rx_chan != SPI_NO_RESOURCE &&
+ dma_tx_chan != SPI_NO_RESOURCE &&
+ dma_eventq != SPI_NO_RESOURCE) {
+ davinci_spi->dma_channels.dma_rx_channel = dma_rx_chan;
+ davinci_spi->dma_channels.dma_tx_channel = dma_tx_chan;
davinci_spi->dma_channels.eventq = dma_eventq;
+ ret = davinci_spi_request_dma(&davinci_spi->dma_channels);
+ if (ret)
+ goto free_clk;
+
+ davinci_spi->bitbang.txrx_bufs = davinci_spi_bufs_dma;
dev_info(&pdev->dev, "DaVinci SPI driver in EDMA mode\n"
"Using RX channel = %d , TX channel = %d and "
"event queue = %d", dma_rx_chan, dma_tx_chan,
@@ -1015,12 +961,15 @@ static int davinci_spi_probe(struct platform_device *pdev)
ret = spi_bitbang_start(&davinci_spi->bitbang);
if (ret)
- goto free_clk;
+ goto free_dma;
dev_info(&pdev->dev, "Controller at 0x%p\n", davinci_spi->base);
return ret;
+free_dma:
+ edma_free_channel(davinci_spi->dma_channels.dma_tx_channel);
+ edma_free_channel(davinci_spi->dma_channels.dma_rx_channel);
free_clk:
clk_disable(davinci_spi->clk);
clk_put(davinci_spi->clk);
OpenPOWER on IntegriCloud