diff options
Diffstat (limited to 'drivers/spi/dw_spi.c')
-rw-r--r-- | drivers/spi/dw_spi.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c index b50bf5ba873f..497ecb3ab83f 100644 --- a/drivers/spi/dw_spi.c +++ b/drivers/spi/dw_spi.c @@ -288,8 +288,10 @@ static void *next_transfer(struct dw_spi *dws) */ static int map_dma_buffers(struct dw_spi *dws) { - if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited - || !dws->cur_chip->enable_dma) + if (!dws->cur_msg->is_dma_mapped + || !dws->dma_inited + || !dws->cur_chip->enable_dma + || !dws->dma_ops) return 0; if (dws->cur_transfer->tx_dma) @@ -341,7 +343,7 @@ static void int_error_stop(struct dw_spi *dws, const char *msg) tasklet_schedule(&dws->pump_transfers); } -static void transfer_complete(struct dw_spi *dws) +void dw_spi_xfer_done(struct dw_spi *dws) { /* Update total byte transfered return count actual bytes read */ dws->cur_msg->actual_length += dws->len; @@ -356,6 +358,7 @@ static void transfer_complete(struct dw_spi *dws) } else tasklet_schedule(&dws->pump_transfers); } +EXPORT_SYMBOL_GPL(dw_spi_xfer_done); static irqreturn_t interrupt_transfer(struct dw_spi *dws) { @@ -387,7 +390,7 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) if (dws->tx_end > dws->tx) spi_umask_intr(dws, SPI_INT_TXEI); else - transfer_complete(dws); + dw_spi_xfer_done(dws); } return IRQ_HANDLED; @@ -422,11 +425,7 @@ static void poll_transfer(struct dw_spi *dws) */ dws->read(dws); - transfer_complete(dws); -} - -static void dma_transfer(struct dw_spi *dws, int cs_change) -{ + dw_spi_xfer_done(dws); } static void pump_transfers(unsigned long data) @@ -608,7 +607,7 @@ static void pump_transfers(unsigned long data) } if (dws->dma_mapped) - dma_transfer(dws, cs_change); + dws->dma_ops->dma_transfer(dws, cs_change); if (chip->poll_mode) poll_transfer(dws); @@ -904,11 +903,17 @@ int __devinit dw_spi_add_host(struct dw_spi *dws) master->setup = dw_spi_setup; master->transfer = dw_spi_transfer; - dws->dma_inited = 0; - /* Basic HW init */ spi_hw_init(dws); + if (dws->dma_ops && dws->dma_ops->dma_init) { + ret = dws->dma_ops->dma_init(dws); + if (ret) { + dev_warn(&master->dev, "DMA init failed\n"); + dws->dma_inited = 0; + } + } + /* Initial and start queue */ ret = init_queue(dws); if (ret) { @@ -933,6 +938,8 @@ int __devinit dw_spi_add_host(struct dw_spi *dws) err_queue_alloc: destroy_queue(dws); + if (dws->dma_ops && dws->dma_ops->dma_exit) + dws->dma_ops->dma_exit(dws); err_diable_hw: spi_enable_chip(dws, 0); free_irq(dws->irq, dws); @@ -957,6 +964,8 @@ void __devexit dw_spi_remove_host(struct dw_spi *dws) dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not " "complete, message memory not freed\n"); + if (dws->dma_ops && dws->dma_ops->dma_exit) + dws->dma_ops->dma_exit(dws); spi_enable_chip(dws, 0); /* Disable clk */ spi_set_clk(dws, 0); |