summaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert+renesas@glider.be>2014-06-02 15:38:09 +0200
committerMark Brown <broonie@linaro.org>2014-06-02 16:49:33 +0200
commit65bf220571f131a7c3a564a88793bd0f16fd7c96 (patch)
tree112cd6651ff046bc62cba333ad01ee5c7bfdd857 /drivers/spi
parentspi: rspi: Don't consider DMA configuration failures fatal (diff)
downloadlinux-65bf220571f131a7c3a564a88793bd0f16fd7c96.tar.xz
linux-65bf220571f131a7c3a564a88793bd0f16fd7c96.zip
spi: rspi: Extract rspi_request_dma_chan()
Setup of the receive and transmit DMA channels is very similar, so let's consolidate. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-rspi.c89
1 files changed, 55 insertions, 34 deletions
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 94a99ec7d989..0a7a2d618f0f 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -942,52 +942,73 @@ static irqreturn_t rspi_irq_tx(int irq, void *_sr)
return 0;
}
-static int rspi_request_dma(struct rspi_data *rspi,
- struct platform_device *pdev)
+static struct dma_chan *rspi_request_dma_chan(struct device *dev,
+ enum dma_transfer_direction dir,
+ unsigned int id,
+ dma_addr_t port_addr)
{
- const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
- struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dma_cap_mask_t mask;
+ struct dma_chan *chan;
struct dma_slave_config cfg;
int ret;
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ chan = dma_request_channel(mask, shdma_chan_filter,
+ (void *)(unsigned long)id);
+ if (!chan) {
+ dev_warn(dev, "dma_request_channel failed\n");
+ return NULL;
+ }
+
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.slave_id = id;
+ cfg.direction = dir;
+ if (dir == DMA_MEM_TO_DEV)
+ cfg.dst_addr = port_addr;
+ else
+ cfg.src_addr = port_addr;
+
+ ret = dmaengine_slave_config(chan, &cfg);
+ if (ret) {
+ dev_warn(dev, "dmaengine_slave_config failed %d\n", ret);
+ dma_release_channel(chan);
+ return NULL;
+ }
+
+ return chan;
+}
+
+static int rspi_request_dma(struct rspi_data *rspi,
+ struct platform_device *pdev)
+{
+ const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
if (!res || !rspi_pd)
return 0; /* The driver assumes no error. */
/* If the module receives data by DMAC, it also needs TX DMAC */
if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) {
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter,
- (void *)rspi_pd->dma_rx_id);
- if (rspi->chan_rx) {
- cfg.slave_id = rspi_pd->dma_rx_id;
- cfg.direction = DMA_DEV_TO_MEM;
- cfg.dst_addr = 0;
- cfg.src_addr = res->start + RSPI_SPDR;
- ret = dmaengine_slave_config(rspi->chan_rx, &cfg);
- if (!ret)
- dev_info(&pdev->dev, "Use DMA when rx.\n");
- else
- return ret;
- }
+ rspi->chan_rx = rspi_request_dma_chan(&pdev->dev,
+ DMA_DEV_TO_MEM,
+ rspi_pd->dma_rx_id,
+ res->start + RSPI_SPDR);
+ if (!rspi->chan_rx)
+ return -ENODEV;
+
+ dev_info(&pdev->dev, "Use DMA when rx.\n");
}
if (rspi_pd->dma_tx_id) {
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter,
- (void *)rspi_pd->dma_tx_id);
- if (rspi->chan_tx) {
- cfg.slave_id = rspi_pd->dma_tx_id;
- cfg.direction = DMA_MEM_TO_DEV;
- cfg.dst_addr = res->start + RSPI_SPDR;
- cfg.src_addr = 0;
- ret = dmaengine_slave_config(rspi->chan_tx, &cfg);
- if (!ret)
- dev_info(&pdev->dev, "Use DMA when tx\n");
- else
- return ret;
- }
+ rspi->chan_tx = rspi_request_dma_chan(&pdev->dev,
+ DMA_MEM_TO_DEV,
+ rspi_pd->dma_tx_id,
+ res->start + RSPI_SPDR);
+ if (!rspi->chan_tx)
+ return -ENODEV;
+
+ dev_info(&pdev->dev, "Use DMA when tx\n");
}
return 0;