aboutsummaryrefslogtreecommitdiff
path: root/drivers/spi/spi_bfin5xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi_bfin5xx.c')
-rw-r--r--drivers/spi/spi_bfin5xx.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index b797ece0b10..88dee87fc42 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -761,11 +761,10 @@ static void pump_transfers(unsigned long data)
if (!full_duplex && drv_data->cur_chip->enable_dma
&& drv_data->len > 6) {
- unsigned long dma_start_addr;
+ unsigned long dma_start_addr, flags;
disable_dma(drv_data->dma_channel);
clear_dma_irqstat(drv_data->dma_channel);
- bfin_spi_disable(drv_data);
/* config dma channel */
dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
@@ -796,8 +795,7 @@ static void pump_transfers(unsigned long data)
enable_dma(drv_data->dma_channel);
/* start SPI transfer */
- write_CTRL(drv_data,
- (cr | BIT_CTL_TIMOD_DMA_TX | BIT_CTL_ENABLE));
+ write_CTRL(drv_data, cr | BIT_CTL_TIMOD_DMA_TX);
/* just return here, there can only be one transfer
* in this mode
@@ -842,14 +840,22 @@ static void pump_transfers(unsigned long data)
} else
BUG();
- /* start dma */
- dma_enable_irq(drv_data->dma_channel);
- set_dma_config(drv_data->dma_channel, dma_config);
+ /* oh man, here there be monsters ... and i dont mean the
+ * fluffy cute ones from pixar, i mean the kind that'll eat
+ * your data, kick your dog, and love it all. do *not* try
+ * and change these lines unless you (1) heavily test DMA
+ * with SPI flashes on a loaded system (e.g. ping floods),
+ * (2) know just how broken the DMA engine interaction with
+ * the SPI peripheral is, and (3) have someone else to blame
+ * when you screw it all up anyways.
+ */
set_dma_start_addr(drv_data->dma_channel, dma_start_addr);
+ set_dma_config(drv_data->dma_channel, dma_config);
+ local_irq_save(flags);
enable_dma(drv_data->dma_channel);
-
- /* start SPI transfer */
- write_CTRL(drv_data, (cr | BIT_CTL_ENABLE));
+ write_CTRL(drv_data, cr);
+ dma_enable_irq(drv_data->dma_channel);
+ local_irq_restore(flags);
} else {
/* IO mode write then read */