From: Russell King <rmk+kernel@arm.linux.org.uk> To: linux-arm-kernel@lists.infradead.org, linux-omap@vger.kernel.org Cc: Grant Likely <grant.likely@secretlab.ca>, spi-devel-general@lists.sourceforge.net Subject: [CFT 07/11] spi: omap2-mcspi: add DMA engine support Date: Thu, 07 Jun 2012 12:08:35 +0100 [thread overview] Message-ID: <E1ScaZv-0003tz-6F@rmk-PC.arm.linux.org.uk> (raw) In-Reply-To: <20120607110610.GB15973@n2100.arm.linux.org.uk> Add DMA engine support to the OMAP SPI driver. This supplements the private DMA API implementation contained within this driver, and the driver can be independently switched at build time between using DMA engine and the private DMA API for the transmit and receive sides. Tested-by: Shubhrajyoti <shubhrajyoti@ti.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- drivers/spi/spi-omap2-mcspi.c | 183 +++++++++++++++++++++++++++++++++------- 1 files changed, 151 insertions(+), 32 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 46ef5fe..ca016df 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -20,6 +20,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ +#define USE_DMA_ENGINE_RX +#define USE_DMA_ENGINE_TX #include <linux/kernel.h> #include <linux/init.h> @@ -28,6 +30,8 @@ #include <linux/device.h> #include <linux/delay.h> #include <linux/dma-mapping.h> +#include <linux/dmaengine.h> +#include <linux/omap-dma.h> #include <linux/platform_device.h> #include <linux/err.h> #include <linux/clk.h> @@ -93,6 +97,8 @@ /* We have 2 DMA channels per CS, one for RX and one for TX */ struct omap2_mcspi_dma { + struct dma_chan *dma_tx; + struct dma_chan *dma_rx; int dma_tx_channel; int dma_rx_channel; @@ -300,6 +306,30 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) return 0; } +static void omap2_mcspi_rx_callback(void *data) +{ + struct spi_device *spi = data; + struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); + struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; + + complete(&mcspi_dma->dma_rx_completion); + + /* We must disable the DMA RX request */ + omap2_mcspi_set_dma_req(spi, 1, 0); +} + +static void omap2_mcspi_tx_callback(void *data) +{ + struct spi_device *spi = data; + struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); + struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; + + complete(&mcspi_dma->dma_tx_completion); + + /* We must disable the DMA TX request */ + omap2_mcspi_set_dma_req(spi, 0, 0); +} + static unsigned omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) { @@ -314,6 +344,9 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) u8 * rx; const u8 * tx; void __iomem *chstat_reg; + struct dma_slave_config cfg; + enum dma_slave_buswidth width; + unsigned es; mcspi = spi_master_get_devdata(spi->master); mcspi_dma = &mcspi->dma_channels[spi->chip_select]; @@ -321,6 +354,71 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; + if (cs->word_len <= 8) { + width = DMA_SLAVE_BUSWIDTH_1_BYTE; + es = 1; + } else if (cs->word_len <= 16) { + width = DMA_SLAVE_BUSWIDTH_2_BYTES; + es = 2; + } else { + width = DMA_SLAVE_BUSWIDTH_4_BYTES; + es = 4; + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0; + cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0; + cfg.src_addr_width = width; + cfg.dst_addr_width = width; + cfg.src_maxburst = 1; + cfg.dst_maxburst = 1; + + if (xfer->tx_buf && mcspi_dma->dma_tx) { + struct dma_async_tx_descriptor *tx; + struct scatterlist sg; + + dmaengine_slave_config(mcspi_dma->dma_tx, &cfg); + + sg_init_table(&sg, 1); + sg_dma_address(&sg) = xfer->tx_dma; + sg_dma_len(&sg) = xfer->len; + + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (tx) { + tx->callback = omap2_mcspi_tx_callback; + tx->callback_param = spi; + dmaengine_submit(tx); + } else { + /* FIXME: fall back to PIO? */ + } + } + + if (xfer->rx_buf && mcspi_dma->dma_rx) { + struct dma_async_tx_descriptor *tx; + struct scatterlist sg; + size_t len = xfer->len - es; + + dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); + + if (l & OMAP2_MCSPI_CHCONF_TURBO) + len -= es; + + sg_init_table(&sg, 1); + sg_dma_address(&sg) = xfer->rx_dma; + sg_dma_len(&sg) = len; + + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (tx) { + tx->callback = omap2_mcspi_rx_callback; + tx->callback_param = spi; + dmaengine_submit(tx); + } else { + /* FIXME: fall back to PIO? */ + } + } + count = xfer->len; c = count; word_len = cs->word_len; @@ -342,7 +440,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) element_count = count >> 2; } - if (tx != NULL) { + if (tx != NULL && mcspi_dma->dma_tx_channel != -1) { omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel, data_type, element_count, 1, OMAP_DMA_SYNC_ELEMENT, @@ -357,7 +455,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) xfer->tx_dma, 0, 0); } - if (rx != NULL) { + if (rx != NULL && mcspi_dma->dma_rx_channel != -1) { elements = element_count - 1; if (l & OMAP2_MCSPI_CHCONF_TURBO) elements--; @@ -377,12 +475,18 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) } if (tx != NULL) { - omap_start_dma(mcspi_dma->dma_tx_channel); + if (mcspi_dma->dma_tx) + dma_async_issue_pending(mcspi_dma->dma_tx); + else + omap_start_dma(mcspi_dma->dma_tx_channel); omap2_mcspi_set_dma_req(spi, 0, 1); } if (rx != NULL) { - omap_start_dma(mcspi_dma->dma_rx_channel); + if (mcspi_dma->dma_rx) + dma_async_issue_pending(mcspi_dma->dma_rx); + else + omap_start_dma(mcspi_dma->dma_rx_channel); omap2_mcspi_set_dma_req(spi, 1, 1); } @@ -406,7 +510,10 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) dma_unmap_single(&spi->dev, xfer->rx_dma, count, DMA_FROM_DEVICE); omap2_mcspi_set_enable(spi, 0); + elements = element_count - 1; + if (l & OMAP2_MCSPI_CHCONF_TURBO) { + elements--; if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) & OMAP2_MCSPI_CHSTAT_RXS)) { @@ -725,32 +832,12 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, static void omap2_mcspi_dma_rx_callback(int lch, u16 ch_status, void *data) { - struct spi_device *spi = data; - struct omap2_mcspi *mcspi; - struct omap2_mcspi_dma *mcspi_dma; - - mcspi = spi_master_get_devdata(spi->master); - mcspi_dma = &(mcspi->dma_channels[spi->chip_select]); - - complete(&mcspi_dma->dma_rx_completion); - - /* We must disable the DMA RX request */ - omap2_mcspi_set_dma_req(spi, 1, 0); + omap2_mcspi_rx_callback(data); } static void omap2_mcspi_dma_tx_callback(int lch, u16 ch_status, void *data) { - struct spi_device *spi = data; - struct omap2_mcspi *mcspi; - struct omap2_mcspi_dma *mcspi_dma; - - mcspi = spi_master_get_devdata(spi->master); - mcspi_dma = &(mcspi->dma_channels[spi->chip_select]); - - complete(&mcspi_dma->dma_tx_completion); - - /* We must disable the DMA TX request */ - omap2_mcspi_set_dma_req(spi, 0, 0); + omap2_mcspi_tx_callback(data); } static int omap2_mcspi_request_dma(struct spi_device *spi) @@ -758,17 +845,43 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) struct spi_master *master = spi->master; struct omap2_mcspi *mcspi; struct omap2_mcspi_dma *mcspi_dma; + dma_cap_mask_t mask; + unsigned sig; mcspi = spi_master_get_devdata(master); mcspi_dma = mcspi->dma_channels + spi->chip_select; + init_completion(&mcspi_dma->dma_rx_completion); + init_completion(&mcspi_dma->dma_tx_completion); + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); +#ifdef USE_DMA_ENGINE_RX + sig = mcspi_dma->dma_rx_sync_dev; + mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig); + if (!mcspi_dma->dma_rx) { + dev_err(&spi->dev, "no RX DMA engine channel for McSPI\n"); + return -EAGAIN; + } +#else if (omap_request_dma(mcspi_dma->dma_rx_sync_dev, "McSPI RX", omap2_mcspi_dma_rx_callback, spi, &mcspi_dma->dma_rx_channel)) { dev_err(&spi->dev, "no RX DMA channel for McSPI\n"); return -EAGAIN; } +#endif +#ifdef USE_DMA_ENGINE_TX + sig = mcspi_dma->dma_tx_sync_dev; + mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig); + if (!mcspi_dma->dma_tx) { + dev_err(&spi->dev, "no TX DMA engine channel for McSPI\n"); + dma_release_channel(mcspi_dma->dma_rx); + mcspi_dma->dma_rx = NULL; + return -EAGAIN; + } +#else if (omap_request_dma(mcspi_dma->dma_tx_sync_dev, "McSPI TX", omap2_mcspi_dma_tx_callback, spi, &mcspi_dma->dma_tx_channel)) { @@ -777,9 +890,7 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) dev_err(&spi->dev, "no TX DMA channel for McSPI\n"); return -EAGAIN; } - - init_completion(&mcspi_dma->dma_rx_completion); - init_completion(&mcspi_dma->dma_tx_completion); +#endif return 0; } @@ -812,8 +923,8 @@ static int omap2_mcspi_setup(struct spi_device *spi) list_add_tail(&cs->node, &ctx->cs); } - if (mcspi_dma->dma_rx_channel == -1 - || mcspi_dma->dma_tx_channel == -1) { + if ((!mcspi_dma->dma_rx && mcspi_dma->dma_rx_channel == -1) || + (!mcspi_dma->dma_tx && mcspi_dma->dma_tx_channel == -1)) { ret = omap2_mcspi_request_dma(spi); if (ret < 0) return ret; @@ -847,6 +958,14 @@ static void omap2_mcspi_cleanup(struct spi_device *spi) if (spi->chip_select < spi->master->num_chipselect) { mcspi_dma = &mcspi->dma_channels[spi->chip_select]; + if (mcspi_dma->dma_rx) { + dma_release_channel(mcspi_dma->dma_rx); + mcspi_dma->dma_rx = NULL; + } + if (mcspi_dma->dma_tx) { + dma_release_channel(mcspi_dma->dma_tx); + mcspi_dma->dma_tx = NULL; + } if (mcspi_dma->dma_rx_channel != -1) { omap_free_dma(mcspi_dma->dma_rx_channel); mcspi_dma->dma_rx_channel = -1; -- 1.7.4.4
WARNING: multiple messages have this Message-ID (diff)
From: rmk+kernel@arm.linux.org.uk (Russell King) To: linux-arm-kernel@lists.infradead.org Subject: [CFT 07/11] spi: omap2-mcspi: add DMA engine support Date: Thu, 07 Jun 2012 12:08:35 +0100 [thread overview] Message-ID: <E1ScaZv-0003tz-6F@rmk-PC.arm.linux.org.uk> (raw) In-Reply-To: <20120607110610.GB15973@n2100.arm.linux.org.uk> Add DMA engine support to the OMAP SPI driver. This supplements the private DMA API implementation contained within this driver, and the driver can be independently switched at build time between using DMA engine and the private DMA API for the transmit and receive sides. Tested-by: Shubhrajyoti <shubhrajyoti@ti.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- drivers/spi/spi-omap2-mcspi.c | 183 +++++++++++++++++++++++++++++++++------- 1 files changed, 151 insertions(+), 32 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 46ef5fe..ca016df 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -20,6 +20,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ +#define USE_DMA_ENGINE_RX +#define USE_DMA_ENGINE_TX #include <linux/kernel.h> #include <linux/init.h> @@ -28,6 +30,8 @@ #include <linux/device.h> #include <linux/delay.h> #include <linux/dma-mapping.h> +#include <linux/dmaengine.h> +#include <linux/omap-dma.h> #include <linux/platform_device.h> #include <linux/err.h> #include <linux/clk.h> @@ -93,6 +97,8 @@ /* We have 2 DMA channels per CS, one for RX and one for TX */ struct omap2_mcspi_dma { + struct dma_chan *dma_tx; + struct dma_chan *dma_rx; int dma_tx_channel; int dma_rx_channel; @@ -300,6 +306,30 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) return 0; } +static void omap2_mcspi_rx_callback(void *data) +{ + struct spi_device *spi = data; + struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); + struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; + + complete(&mcspi_dma->dma_rx_completion); + + /* We must disable the DMA RX request */ + omap2_mcspi_set_dma_req(spi, 1, 0); +} + +static void omap2_mcspi_tx_callback(void *data) +{ + struct spi_device *spi = data; + struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); + struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; + + complete(&mcspi_dma->dma_tx_completion); + + /* We must disable the DMA TX request */ + omap2_mcspi_set_dma_req(spi, 0, 0); +} + static unsigned omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) { @@ -314,6 +344,9 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) u8 * rx; const u8 * tx; void __iomem *chstat_reg; + struct dma_slave_config cfg; + enum dma_slave_buswidth width; + unsigned es; mcspi = spi_master_get_devdata(spi->master); mcspi_dma = &mcspi->dma_channels[spi->chip_select]; @@ -321,6 +354,71 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; + if (cs->word_len <= 8) { + width = DMA_SLAVE_BUSWIDTH_1_BYTE; + es = 1; + } else if (cs->word_len <= 16) { + width = DMA_SLAVE_BUSWIDTH_2_BYTES; + es = 2; + } else { + width = DMA_SLAVE_BUSWIDTH_4_BYTES; + es = 4; + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0; + cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0; + cfg.src_addr_width = width; + cfg.dst_addr_width = width; + cfg.src_maxburst = 1; + cfg.dst_maxburst = 1; + + if (xfer->tx_buf && mcspi_dma->dma_tx) { + struct dma_async_tx_descriptor *tx; + struct scatterlist sg; + + dmaengine_slave_config(mcspi_dma->dma_tx, &cfg); + + sg_init_table(&sg, 1); + sg_dma_address(&sg) = xfer->tx_dma; + sg_dma_len(&sg) = xfer->len; + + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (tx) { + tx->callback = omap2_mcspi_tx_callback; + tx->callback_param = spi; + dmaengine_submit(tx); + } else { + /* FIXME: fall back to PIO? */ + } + } + + if (xfer->rx_buf && mcspi_dma->dma_rx) { + struct dma_async_tx_descriptor *tx; + struct scatterlist sg; + size_t len = xfer->len - es; + + dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); + + if (l & OMAP2_MCSPI_CHCONF_TURBO) + len -= es; + + sg_init_table(&sg, 1); + sg_dma_address(&sg) = xfer->rx_dma; + sg_dma_len(&sg) = len; + + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (tx) { + tx->callback = omap2_mcspi_rx_callback; + tx->callback_param = spi; + dmaengine_submit(tx); + } else { + /* FIXME: fall back to PIO? */ + } + } + count = xfer->len; c = count; word_len = cs->word_len; @@ -342,7 +440,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) element_count = count >> 2; } - if (tx != NULL) { + if (tx != NULL && mcspi_dma->dma_tx_channel != -1) { omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel, data_type, element_count, 1, OMAP_DMA_SYNC_ELEMENT, @@ -357,7 +455,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) xfer->tx_dma, 0, 0); } - if (rx != NULL) { + if (rx != NULL && mcspi_dma->dma_rx_channel != -1) { elements = element_count - 1; if (l & OMAP2_MCSPI_CHCONF_TURBO) elements--; @@ -377,12 +475,18 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) } if (tx != NULL) { - omap_start_dma(mcspi_dma->dma_tx_channel); + if (mcspi_dma->dma_tx) + dma_async_issue_pending(mcspi_dma->dma_tx); + else + omap_start_dma(mcspi_dma->dma_tx_channel); omap2_mcspi_set_dma_req(spi, 0, 1); } if (rx != NULL) { - omap_start_dma(mcspi_dma->dma_rx_channel); + if (mcspi_dma->dma_rx) + dma_async_issue_pending(mcspi_dma->dma_rx); + else + omap_start_dma(mcspi_dma->dma_rx_channel); omap2_mcspi_set_dma_req(spi, 1, 1); } @@ -406,7 +510,10 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) dma_unmap_single(&spi->dev, xfer->rx_dma, count, DMA_FROM_DEVICE); omap2_mcspi_set_enable(spi, 0); + elements = element_count - 1; + if (l & OMAP2_MCSPI_CHCONF_TURBO) { + elements--; if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) & OMAP2_MCSPI_CHSTAT_RXS)) { @@ -725,32 +832,12 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, static void omap2_mcspi_dma_rx_callback(int lch, u16 ch_status, void *data) { - struct spi_device *spi = data; - struct omap2_mcspi *mcspi; - struct omap2_mcspi_dma *mcspi_dma; - - mcspi = spi_master_get_devdata(spi->master); - mcspi_dma = &(mcspi->dma_channels[spi->chip_select]); - - complete(&mcspi_dma->dma_rx_completion); - - /* We must disable the DMA RX request */ - omap2_mcspi_set_dma_req(spi, 1, 0); + omap2_mcspi_rx_callback(data); } static void omap2_mcspi_dma_tx_callback(int lch, u16 ch_status, void *data) { - struct spi_device *spi = data; - struct omap2_mcspi *mcspi; - struct omap2_mcspi_dma *mcspi_dma; - - mcspi = spi_master_get_devdata(spi->master); - mcspi_dma = &(mcspi->dma_channels[spi->chip_select]); - - complete(&mcspi_dma->dma_tx_completion); - - /* We must disable the DMA TX request */ - omap2_mcspi_set_dma_req(spi, 0, 0); + omap2_mcspi_tx_callback(data); } static int omap2_mcspi_request_dma(struct spi_device *spi) @@ -758,17 +845,43 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) struct spi_master *master = spi->master; struct omap2_mcspi *mcspi; struct omap2_mcspi_dma *mcspi_dma; + dma_cap_mask_t mask; + unsigned sig; mcspi = spi_master_get_devdata(master); mcspi_dma = mcspi->dma_channels + spi->chip_select; + init_completion(&mcspi_dma->dma_rx_completion); + init_completion(&mcspi_dma->dma_tx_completion); + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); +#ifdef USE_DMA_ENGINE_RX + sig = mcspi_dma->dma_rx_sync_dev; + mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig); + if (!mcspi_dma->dma_rx) { + dev_err(&spi->dev, "no RX DMA engine channel for McSPI\n"); + return -EAGAIN; + } +#else if (omap_request_dma(mcspi_dma->dma_rx_sync_dev, "McSPI RX", omap2_mcspi_dma_rx_callback, spi, &mcspi_dma->dma_rx_channel)) { dev_err(&spi->dev, "no RX DMA channel for McSPI\n"); return -EAGAIN; } +#endif +#ifdef USE_DMA_ENGINE_TX + sig = mcspi_dma->dma_tx_sync_dev; + mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig); + if (!mcspi_dma->dma_tx) { + dev_err(&spi->dev, "no TX DMA engine channel for McSPI\n"); + dma_release_channel(mcspi_dma->dma_rx); + mcspi_dma->dma_rx = NULL; + return -EAGAIN; + } +#else if (omap_request_dma(mcspi_dma->dma_tx_sync_dev, "McSPI TX", omap2_mcspi_dma_tx_callback, spi, &mcspi_dma->dma_tx_channel)) { @@ -777,9 +890,7 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) dev_err(&spi->dev, "no TX DMA channel for McSPI\n"); return -EAGAIN; } - - init_completion(&mcspi_dma->dma_rx_completion); - init_completion(&mcspi_dma->dma_tx_completion); +#endif return 0; } @@ -812,8 +923,8 @@ static int omap2_mcspi_setup(struct spi_device *spi) list_add_tail(&cs->node, &ctx->cs); } - if (mcspi_dma->dma_rx_channel == -1 - || mcspi_dma->dma_tx_channel == -1) { + if ((!mcspi_dma->dma_rx && mcspi_dma->dma_rx_channel == -1) || + (!mcspi_dma->dma_tx && mcspi_dma->dma_tx_channel == -1)) { ret = omap2_mcspi_request_dma(spi); if (ret < 0) return ret; @@ -847,6 +958,14 @@ static void omap2_mcspi_cleanup(struct spi_device *spi) if (spi->chip_select < spi->master->num_chipselect) { mcspi_dma = &mcspi->dma_channels[spi->chip_select]; + if (mcspi_dma->dma_rx) { + dma_release_channel(mcspi_dma->dma_rx); + mcspi_dma->dma_rx = NULL; + } + if (mcspi_dma->dma_tx) { + dma_release_channel(mcspi_dma->dma_tx); + mcspi_dma->dma_tx = NULL; + } if (mcspi_dma->dma_rx_channel != -1) { omap_free_dma(mcspi_dma->dma_rx_channel); mcspi_dma->dma_rx_channel = -1; -- 1.7.4.4
next prev parent reply other threads:[~2012-06-07 11:08 UTC|newest] Thread overview: 172+ messages / expand[flat|nested] mbox.gz Atom feed top 2012-06-07 10:34 [CFT] DMA engine patches Russell King - ARM Linux 2012-06-07 10:34 ` Russell King - ARM Linux 2012-06-07 10:40 ` [CFT 1/3] dmaengine: split out virtual channel DMA support from sa11x0 driver Russell King 2012-06-07 10:40 ` Russell King 2012-06-07 10:41 ` [CFT 2/3] dmaengine: virt-dma: vchan_find_desc() Russell King 2012-06-07 10:41 ` Russell King 2012-06-07 10:41 ` [CFT 3/3] dmaengine: virt-dma: add support for cyclic DMA periodic callbacks Russell King 2012-06-07 10:41 ` Russell King 2012-06-07 10:42 ` [CFT] SA11x0 patches Russell King - ARM Linux 2012-06-07 10:42 ` Russell King - ARM Linux 2012-06-07 10:43 ` [CFT 1/2] dmaengine: sa11x0-dma: fix DMA residue support Russell King 2012-06-07 10:43 ` Russell King 2012-06-07 10:43 ` [CFT 2/2] dmaengine: sa11x0-dma: add cyclic DMA support Russell King 2012-06-07 10:43 ` Russell King 2012-06-07 10:45 ` [CFT] PL08x patches Russell King - ARM Linux 2012-06-07 10:45 ` Russell King - ARM Linux 2012-06-07 10:46 ` [CFT 01/31] dmaengine: PL08x: remove runtime PM support Russell King 2012-06-07 10:46 ` Russell King 2012-06-07 10:46 ` [CFT 02/31] dmaengine: PL08x: fix missed dma_transfer_direction fixup Russell King 2012-06-07 10:46 ` Russell King 2012-06-07 10:46 ` [CFT 03/31] dmaengine: PL08x: remove redundant spinlock Russell King 2012-06-07 10:46 ` Russell King 2012-06-07 10:47 ` [CFT 04/31] dmaengine: PL08x: remove circular_buffer boolean from channel data Russell King 2012-06-07 10:47 ` Russell King 2012-06-07 10:47 ` [CFT 05/31] dmaengine: PL08x: clean up get_signal/put_signal Russell King 2012-06-07 10:47 ` Russell King 2012-06-10 10:03 ` Russell King - ARM Linux 2012-06-10 10:03 ` Russell King - ARM Linux 2012-06-07 10:47 ` [CFT 06/31] dmaengine: PL08x: move private data structures into amba-pl08x.c Russell King 2012-06-07 10:47 ` Russell King 2012-06-07 10:48 ` [CFT 07/31] dmaengine: PL08x: constify channel names and bus_id strings Russell King 2012-06-07 10:48 ` Russell King 2012-06-07 10:48 ` [CFT 08/31] dmaengine: PL08x: get src/dst addr direct from dma_slave_config struct Russell King 2012-06-07 10:48 ` Russell King 2012-06-07 10:48 ` [CFT 09/31] dmaengine: PL08x: get rid of device_fc in struct pl08x_dma_chan Russell King 2012-06-07 10:48 ` Russell King 2012-06-07 10:49 ` [CFT 10/31] dmaengine: PL08x: move the bus and increment selection to dma prepare function Russell King 2012-06-07 10:49 ` Russell King 2012-06-07 10:49 ` [CFT 11/31] dmaengine: PL08x: extract function to to generate cctl values Russell King 2012-06-07 10:49 ` Russell King 2012-06-07 10:49 ` [CFT 12/31] dmaengine: PL08x: ignore 'direction' argument in dma_slave_config Russell King 2012-06-07 10:49 ` Russell King 2012-06-07 10:50 ` [CFT 13/31] dmaengine: PL08x: get rid of unnecessary checks " Russell King 2012-06-07 10:50 ` Russell King 2012-06-07 10:50 ` [CFT 14/31] dmaengine: PL08x: split DMA signal muxing from channel alloc Russell King 2012-06-07 10:50 ` Russell King 2012-06-07 10:50 ` [CFT 15/31] dmaengine: PL08x: move DMA signal muxing into pl08x_dma_chan struct Russell King 2012-06-07 10:50 ` Russell King 2012-06-07 10:51 ` [CFT 16/31] dmaengine: PL08x: track mux usage on a per-channel basis Russell King 2012-06-07 10:51 ` Russell King 2012-06-07 10:51 ` [CFT 17/31] dmaengine: PL08x: convert to a list of completed descriptors Russell King 2012-06-07 10:51 ` Russell King 2012-06-07 10:51 ` [CFT 18/31] dmaengine: PL08x: move DMA signal muxing into slave prepare code Russell King 2012-06-07 10:51 ` Russell King 2012-06-07 10:52 ` [CFT 19/31] dmaengine: PL08x: remove waiting descriptor pointer Russell King 2012-06-07 10:52 ` Russell King 2012-06-07 10:52 ` [CFT 20/31] dmaengine: PL08x: re-jig the starting of txds Russell King 2012-06-07 10:52 ` Russell King 2012-06-07 10:52 ` [CFT 21/31] dmaengine: PL08x: split the pend_list in two Russell King 2012-06-07 10:52 ` Russell King 2012-06-07 10:53 ` [CFT 22/31] dmaengine: PL08x: start next descriptor from irq context Russell King 2012-06-07 10:53 ` Russell King 2012-06-07 10:53 ` [CFT 23/31] dmaengine: PL08x: rejig physical channel allocation Russell King 2012-06-07 10:53 ` Russell King 2012-06-07 10:53 ` [CFT 24/31] dmaengine: PL08x: convert to use virt-dma structs Russell King 2012-06-07 10:53 ` Russell King 2012-06-07 10:54 ` [CFT 25/31] dmaengine: PL08x: use vchan's spinlock Russell King 2012-06-07 10:54 ` Russell King 2012-06-07 10:54 ` [CFT 26/31] dmaengine: PL08x: convert to use vchan submitted/issued lists Russell King 2012-06-07 10:54 ` Russell King 2012-06-07 10:54 ` [CFT 27/31] dmaengine: PL08x: convert to use vchan done list Russell King 2012-06-07 10:54 ` Russell King 2012-06-07 10:55 ` [CFT 28/31] dmaengine: PL08x: fix tx_status function to return correct residue Russell King 2012-06-07 10:55 ` Russell King 2012-06-07 10:55 ` [CFT 29/31] dmaengine: PL08x: get rid of pl08x_prep_channel_resources Russell King 2012-06-07 10:55 ` Russell King 2012-06-07 10:55 ` [CFT 30/31] dmaengine: PL08x: get rid of write only pool_ctr and free_txd locking Russell King 2012-06-07 10:55 ` Russell King 2012-06-07 10:56 ` [CFT 31/31] dmaengine: PL08x: ensure all descriptors are freed when channel is released Russell King 2012-06-07 10:56 ` Russell King 2012-06-08 8:32 ` [CFT] PL08x patches Linus Walleij 2012-06-08 8:32 ` Linus Walleij 2012-06-07 11:06 ` [CFT] OMAP patches Russell King - ARM Linux 2012-06-07 11:06 ` Russell King - ARM Linux 2012-06-07 11:06 ` [CFT 01/11] dmaengine: add OMAP DMA engine driver Russell King 2012-06-07 11:06 ` Russell King 2012-06-07 12:40 ` S, Venkatraman 2012-06-07 12:40 ` S, Venkatraman 2012-06-07 12:45 ` S, Venkatraman 2012-06-07 12:45 ` S, Venkatraman 2012-06-08 6:19 ` Shilimkar, Santosh 2012-06-08 6:19 ` Shilimkar, Santosh 2012-06-08 9:02 ` Russell King - ARM Linux 2012-06-08 9:02 ` Russell King - ARM Linux 2012-06-08 10:00 ` Shilimkar, Santosh 2012-06-08 10:00 ` Shilimkar, Santosh 2012-06-08 10:01 ` Russell King - ARM Linux 2012-06-08 10:01 ` Russell King - ARM Linux 2012-06-07 11:06 ` [CFT 02/11] mmc: omap_hsmmc: add DMA engine support Russell King 2012-06-07 11:06 ` Russell King 2012-06-07 17:04 ` Tony Lindgren 2012-06-07 17:04 ` Tony Lindgren 2012-06-08 8:53 ` Linus Walleij 2012-06-08 8:53 ` Linus Walleij 2012-06-07 11:07 ` [CFT 03/11] mmc: omap_hsmmc: remove private DMA API implementation Russell King 2012-06-07 11:07 ` Russell King 2012-06-07 17:04 ` Tony Lindgren 2012-06-07 17:04 ` Tony Lindgren 2012-06-07 17:53 ` S, Venkatraman 2012-06-07 17:53 ` S, Venkatraman 2012-07-10 21:48 ` Kevin Hilman 2012-07-10 21:48 ` Kevin Hilman 2012-06-07 11:07 ` [CFT 04/11] mmc: omap: add DMA engine support Russell King 2012-06-07 11:07 ` Russell King 2012-06-07 17:05 ` Tony Lindgren 2012-06-07 17:05 ` Tony Lindgren 2012-06-08 8:52 ` Linus Walleij 2012-06-08 8:52 ` Linus Walleij 2012-06-07 11:07 ` [CFT 05/11] mmc: omap: remove private DMA API implementation Russell King 2012-06-07 11:07 ` Russell King 2012-06-07 17:05 ` Tony Lindgren 2012-06-07 17:05 ` Tony Lindgren 2012-06-07 11:08 ` [CFT 06/11] ARM: omap: remove mmc platform data dma_mask and initialization Russell King 2012-06-07 11:08 ` Russell King 2012-06-07 17:06 ` Tony Lindgren 2012-06-07 17:06 ` Tony Lindgren 2012-06-07 11:08 ` Russell King [this message] 2012-06-07 11:08 ` [CFT 07/11] spi: omap2-mcspi: add DMA engine support Russell King 2012-06-08 8:50 ` Linus Walleij 2012-06-08 8:50 ` Linus Walleij 2012-06-14 11:53 ` Russell King - ARM Linux 2012-06-14 11:53 ` Russell King - ARM Linux 2012-06-14 12:08 ` Russell King - ARM Linux 2012-06-14 12:08 ` Russell King - ARM Linux 2012-06-14 12:50 ` Russell King - ARM Linux 2012-06-14 12:50 ` Russell King - ARM Linux 2012-06-14 14:07 ` [PATCH] SPI: OMAP: fix over-eager devm_xxx() conversion (was: Re: [CFT 07/11] spi: omap2-mcspi: add DMA engine support) Russell King - ARM Linux 2012-06-14 14:07 ` Russell King - ARM Linux [not found] ` <20120614140712.GH31187-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org> 2012-06-16 10:33 ` Russell King - ARM Linux 2012-06-16 10:33 ` Russell King - ARM Linux 2012-06-18 6:41 ` [CFT 07/11] spi: omap2-mcspi: add DMA engine support Shubhrajyoti 2012-06-18 6:41 ` Shubhrajyoti 2012-06-07 11:08 ` [CFT 08/11] spi: omap2-mcspi: remove private DMA API implementation Russell King 2012-06-07 11:08 ` Russell King 2012-06-07 11:09 ` [CFT 09/11] mtd: omap2: add DMA engine support Russell King 2012-06-07 11:09 ` Russell King 2012-06-07 11:09 ` Russell King 2012-06-07 12:49 ` Artem Bityutskiy 2012-06-07 12:49 ` Artem Bityutskiy 2012-06-07 12:49 ` Artem Bityutskiy 2012-06-07 13:11 ` Russell King - ARM Linux 2012-06-07 13:11 ` Russell King - ARM Linux 2012-06-07 13:11 ` Russell King - ARM Linux 2012-06-07 13:28 ` Artem Bityutskiy 2012-06-07 13:28 ` Artem Bityutskiy 2012-06-07 13:28 ` Artem Bityutskiy 2012-06-07 17:10 ` Tony Lindgren 2012-06-07 17:10 ` Tony Lindgren 2012-06-07 17:10 ` Tony Lindgren 2012-06-07 11:09 ` [CFT 10/11] mtd: omap2: remove private DMA API implementation Russell King 2012-06-07 11:09 ` Russell King 2012-06-07 11:09 ` Russell King 2012-06-07 11:09 ` [CFT 11/11] Add feature removal of old OMAP private DMA implementation Russell King 2012-06-07 11:09 ` Russell King 2012-06-07 17:07 ` Tony Lindgren 2012-06-07 17:07 ` Tony Lindgren 2012-06-08 6:10 ` Shilimkar, Santosh 2012-06-08 6:10 ` Shilimkar, Santosh 2012-06-08 18:37 ` Rob Landley 2012-06-08 18:37 ` Rob Landley 2012-06-09 8:32 ` Russell King - ARM Linux 2012-06-09 8:32 ` Russell King - ARM Linux
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=E1ScaZv-0003tz-6F@rmk-PC.arm.linux.org.uk \ --to=rmk+kernel@arm.linux.org.uk \ --cc=grant.likely@secretlab.ca \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-omap@vger.kernel.org \ --cc=spi-devel-general@lists.sourceforge.net \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.