summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSekhar Nori <nsekhar@ti.com>2010-10-01 11:21:40 +0200
committerSekhar Nori <nsekhar@ti.com>2010-11-18 14:08:34 +0100
commit903ca25b219e28e3513ca4c2ff379fcdf19e057e (patch)
treec1b4ef45ca1925ea056974f4f78b6606014b6b4a
parentspi: davinci: fix DMA event generation stoppage (diff)
downloadlinux-903ca25b219e28e3513ca4c2ff379fcdf19e057e.tar.xz
linux-903ca25b219e28e3513ca4c2ff379fcdf19e057e.zip
spi: davinci: do not allocate DMA channels during SPI device setup
Do not allocate (and de-allocate) SPI DMA channels during setup (and cleanup) for each SPI device. Instead, allocate the DMA channels once duing probe and use them for the life time of the driver. This makes sense since there are dedicated DMA channels meant for SPI use. This also helps remove the unnecessary DMA "sync_dev" variables being used to store DMA channel information. Also, the "use_dma" platform variable is now eliminated since it is possible to check if the platform supports DMA or not based upon whether DMA resources can be found or not. Tested-By: Michael Williamson <michael.williamson@criticallink.com> Tested-By: Brian Niebuhr <bniebuhr@efjohnson.com> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
-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 68db6d5daaf4..f7586a03678c 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 9695f98b03bd..6db478601024 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);