diff options
author | Vitja Makarov <vitja.makarov@gmail.com> | 2009-04-06 22:00:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 11:31:04 -0400 |
commit | 8cf5858c51f88208fe56b195251ab4f21265386c (patch) | |
tree | 6095e2a5f9cb5d0b19afef30fd74bb360c4a42db /drivers/spi/spi_bfin5xx.c | |
parent | 3bcfa9e47a7d1be6faef3be6c4b2049e585e2f38 (diff) |
Blackfin SPI Driver: ensure cache coherency before doing DMA
Flush or invalidate caches before doing DMA transfer, if needed.
[Mike Frysinger <vapier.adi@gmail.com>: add comment to address the
issue "Full duplex only works for non-DMA transfers".]
Signed-off-by: Vitja Makarov <vitja.makarov@gmail.com>
Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/spi/spi_bfin5xx.c')
-rw-r--r-- | drivers/spi/spi_bfin5xx.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 3410b0c55ed2..e440718b3209 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c | |||
@@ -26,6 +26,10 @@ | |||
26 | #include <asm/portmux.h> | 26 | #include <asm/portmux.h> |
27 | #include <asm/bfin5xx_spi.h> | 27 | #include <asm/bfin5xx_spi.h> |
28 | 28 | ||
29 | /* reserved_mem_dcache_on and cache friends */ | ||
30 | #include <asm/cplbinit.h> | ||
31 | #include <asm/cacheflush.h> | ||
32 | |||
29 | #define DRV_NAME "bfin-spi" | 33 | #define DRV_NAME "bfin-spi" |
30 | #define DRV_AUTHOR "Bryan Wu, Luke Yang" | 34 | #define DRV_AUTHOR "Bryan Wu, Luke Yang" |
31 | #define DRV_DESC "Blackfin BF5xx on-chip SPI Controller Driver" | 35 | #define DRV_DESC "Blackfin BF5xx on-chip SPI Controller Driver" |
@@ -738,9 +742,10 @@ static void pump_transfers(unsigned long data) | |||
738 | width, transfer->len); | 742 | width, transfer->len); |
739 | 743 | ||
740 | /* | 744 | /* |
741 | * Try to map dma buffer and do a dma transfer if | 745 | * Try to map dma buffer and do a dma transfer. If successful use, |
742 | * successful use different way to r/w according to | 746 | * different way to r/w according to the enable_dma settings and if |
743 | * drv_data->cur_chip->enable_dma | 747 | * we are not doing a full duplex transfer (since the hardware does |
748 | * not support full duplex DMA transfers). | ||
744 | */ | 749 | */ |
745 | if (!full_duplex && drv_data->cur_chip->enable_dma | 750 | if (!full_duplex && drv_data->cur_chip->enable_dma |
746 | && drv_data->len > 6) { | 751 | && drv_data->len > 6) { |
@@ -795,6 +800,12 @@ static void pump_transfers(unsigned long data) | |||
795 | /* set transfer mode, and enable SPI */ | 800 | /* set transfer mode, and enable SPI */ |
796 | dev_dbg(&drv_data->pdev->dev, "doing DMA in.\n"); | 801 | dev_dbg(&drv_data->pdev->dev, "doing DMA in.\n"); |
797 | 802 | ||
803 | /* invalidate caches, if needed */ | ||
804 | if (bfin_addr_dcachable((unsigned long) drv_data->rx)) | ||
805 | invalidate_dcache_range((unsigned long) drv_data->rx, | ||
806 | (unsigned long) (drv_data->rx + | ||
807 | drv_data->len)); | ||
808 | |||
798 | /* clear tx reg soformer data is not shifted out */ | 809 | /* clear tx reg soformer data is not shifted out */ |
799 | write_TDBR(drv_data, 0xFFFF); | 810 | write_TDBR(drv_data, 0xFFFF); |
800 | 811 | ||
@@ -815,6 +826,12 @@ static void pump_transfers(unsigned long data) | |||
815 | } else if (drv_data->tx != NULL) { | 826 | } else if (drv_data->tx != NULL) { |
816 | dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n"); | 827 | dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n"); |
817 | 828 | ||
829 | /* flush caches, if needed */ | ||
830 | if (bfin_addr_dcachable((unsigned long) drv_data->tx)) | ||
831 | flush_dcache_range((unsigned long) drv_data->tx, | ||
832 | (unsigned long) (drv_data->tx + | ||
833 | drv_data->len)); | ||
834 | |||
818 | /* start dma */ | 835 | /* start dma */ |
819 | dma_enable_irq(drv_data->dma_channel); | 836 | dma_enable_irq(drv_data->dma_channel); |
820 | dma_config = (RESTART | dma_width | DI_EN); | 837 | dma_config = (RESTART | dma_width | DI_EN); |