aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2007-05-21 06:09:17 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-21 12:50:22 -0400
commit23ee968d96ef5ad564c0f0b8a30412fb93137ebb (patch)
treea323c73062fa32a794e254a39c519650f0efe4b9
parentd1b945fdb62f3e6852fea5a8779c0151ac1e55a8 (diff)
Blackfin arch: DMA operation cleanup
1) Disable Interrupts during DMA memcpy to avoid raise conditions. 2) Mark MDMA channel 0 as reserved, since were using it internally. 3) Add DMA based equivalents for insX and outsX. 4) Our insX and outsX only handles len <= 2^16. Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Bryan Wu <bryan.wu@analog.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/blackfin/kernel/bfin_dma_5xx.c204
-rw-r--r--include/asm-blackfin/io.h20
2 files changed, 214 insertions, 10 deletions
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index 14314240718e..1c344acfd487 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -130,7 +130,9 @@ static int __init blackfin_dma_init(void)
130 dma_ch[i].regs = base_addr[i]; 130 dma_ch[i].regs = base_addr[i];
131 mutex_init(&(dma_ch[i].dmalock)); 131 mutex_init(&(dma_ch[i].dmalock));
132 } 132 }
133 133 /* Mark MEMDMA Channel 0 as requested since we're using it internally */
134 dma_ch[CH_MEM_STREAM0_DEST].chan_status = DMA_CHANNEL_REQUESTED;
135 dma_ch[CH_MEM_STREAM0_SRC].chan_status = DMA_CHANNEL_REQUESTED;
134 return 0; 136 return 0;
135} 137}
136 138
@@ -598,9 +600,12 @@ void *dma_memcpy(void *dest, const void *src, size_t size)
598 int direction; /* 1 - address decrease, 0 - address increase */ 600 int direction; /* 1 - address decrease, 0 - address increase */
599 int flag_align; /* 1 - address aligned, 0 - address unaligned */ 601 int flag_align; /* 1 - address aligned, 0 - address unaligned */
600 int flag_2D; /* 1 - 2D DMA needed, 0 - 1D DMA needed */ 602 int flag_2D; /* 1 - 2D DMA needed, 0 - 1D DMA needed */
603 unsigned long flags;
601 604
602 if (size <= 0) 605 if (size <= 0)
603 return NULL; 606 return NULL;
607
608 local_irq_save(flags);
604 609
605 if ((unsigned long)src < memory_end) 610 if ((unsigned long)src < memory_end)
606 blackfin_dcache_flush_range((unsigned int)src, 611 blackfin_dcache_flush_range((unsigned int)src,
@@ -725,6 +730,7 @@ void *dma_memcpy(void *dest, const void *src, size_t size)
725 if ((unsigned long)dest < memory_end) 730 if ((unsigned long)dest < memory_end)
726 blackfin_dcache_invalidate_range((unsigned int)dest, 731 blackfin_dcache_invalidate_range((unsigned int)dest,
727 (unsigned int)(dest + size)); 732 (unsigned int)(dest + size));
733 local_irq_restore(flags);
728 734
729 return dest; 735 return dest;
730} 736}
@@ -732,11 +738,201 @@ EXPORT_SYMBOL(dma_memcpy);
732 738
733void *safe_dma_memcpy(void *dest, const void *src, size_t size) 739void *safe_dma_memcpy(void *dest, const void *src, size_t size)
734{ 740{
735 int flags = 0;
736 void *addr; 741 void *addr;
737 local_irq_save(flags);
738 addr = dma_memcpy(dest, src, size); 742 addr = dma_memcpy(dest, src, size);
739 local_irq_restore(flags);
740 return addr; 743 return addr;
741} 744}
742EXPORT_SYMBOL(safe_dma_memcpy); 745EXPORT_SYMBOL(safe_dma_memcpy);
746
747void dma_outsb(void __iomem *addr, const void *buf, unsigned short len)
748{
749
750 unsigned long flags;
751
752 local_irq_save(flags);
753
754 blackfin_dcache_flush_range((unsigned int)buf,(unsigned int)(buf) + len);
755
756 bfin_write_MDMA_D0_START_ADDR(addr);
757 bfin_write_MDMA_D0_X_COUNT(len);
758 bfin_write_MDMA_D0_X_MODIFY(0);
759 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
760
761 bfin_write_MDMA_S0_START_ADDR(buf);
762 bfin_write_MDMA_S0_X_COUNT(len);
763 bfin_write_MDMA_S0_X_MODIFY(1);
764 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
765
766 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8);
767 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8);
768
769 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
770
771 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
772
773 bfin_write_MDMA_S0_CONFIG(0);
774 bfin_write_MDMA_D0_CONFIG(0);
775 local_irq_restore(flags);
776
777}
778EXPORT_SYMBOL(dma_outsb);
779
780
781void dma_insb(const void __iomem *addr, void *buf, unsigned short len)
782{
783 unsigned long flags;
784
785 local_irq_save(flags);
786 bfin_write_MDMA_D0_START_ADDR(buf);
787 bfin_write_MDMA_D0_X_COUNT(len);
788 bfin_write_MDMA_D0_X_MODIFY(1);
789 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
790
791 bfin_write_MDMA_S0_START_ADDR(addr);
792 bfin_write_MDMA_S0_X_COUNT(len);
793 bfin_write_MDMA_S0_X_MODIFY(0);
794 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
795
796 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8);
797 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8);
798
799 blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len);
800
801 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
802
803 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
804
805 bfin_write_MDMA_S0_CONFIG(0);
806 bfin_write_MDMA_D0_CONFIG(0);
807 local_irq_restore(flags);
808
809}
810EXPORT_SYMBOL(dma_insb);
811
812void dma_outsw(void __iomem *addr, const void *buf, unsigned short len)
813{
814 unsigned long flags;
815
816 local_irq_save(flags);
817
818 blackfin_dcache_flush_range((unsigned int)buf,(unsigned int)(buf) + len);
819
820 bfin_write_MDMA_D0_START_ADDR(addr);
821 bfin_write_MDMA_D0_X_COUNT(len);
822 bfin_write_MDMA_D0_X_MODIFY(0);
823 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
824
825 bfin_write_MDMA_S0_START_ADDR(buf);
826 bfin_write_MDMA_S0_X_COUNT(len);
827 bfin_write_MDMA_S0_X_MODIFY(2);
828 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
829
830 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
831 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
832
833 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
834
835 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
836
837 bfin_write_MDMA_S0_CONFIG(0);
838 bfin_write_MDMA_D0_CONFIG(0);
839 local_irq_restore(flags);
840
841}
842EXPORT_SYMBOL(dma_outsw);
843
844void dma_insw(const void __iomem *addr, void *buf, unsigned short len)
845{
846 unsigned long flags;
847
848 local_irq_save(flags);
849
850 bfin_write_MDMA_D0_START_ADDR(buf);
851 bfin_write_MDMA_D0_X_COUNT(len);
852 bfin_write_MDMA_D0_X_MODIFY(2);
853 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
854
855 bfin_write_MDMA_S0_START_ADDR(addr);
856 bfin_write_MDMA_S0_X_COUNT(len);
857 bfin_write_MDMA_S0_X_MODIFY(0);
858 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
859
860 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
861 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
862
863 blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len);
864
865 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
866
867 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
868
869 bfin_write_MDMA_S0_CONFIG(0);
870 bfin_write_MDMA_D0_CONFIG(0);
871 local_irq_restore(flags);
872
873}
874EXPORT_SYMBOL(dma_insw);
875
876void dma_outsl(void __iomem *addr, const void *buf, unsigned short len)
877{
878 unsigned long flags;
879
880 local_irq_save(flags);
881
882 blackfin_dcache_flush_range((unsigned int)buf,(unsigned int)(buf) + len);
883
884 bfin_write_MDMA_D0_START_ADDR(addr);
885 bfin_write_MDMA_D0_X_COUNT(len);
886 bfin_write_MDMA_D0_X_MODIFY(0);
887 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
888
889 bfin_write_MDMA_S0_START_ADDR(buf);
890 bfin_write_MDMA_S0_X_COUNT(len);
891 bfin_write_MDMA_S0_X_MODIFY(4);
892 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
893
894 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32);
895 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32);
896
897 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
898
899 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
900
901 bfin_write_MDMA_S0_CONFIG(0);
902 bfin_write_MDMA_D0_CONFIG(0);
903 local_irq_restore(flags);
904
905}
906EXPORT_SYMBOL(dma_outsl);
907
908void dma_insl(const void __iomem *addr, void *buf, unsigned short len)
909{
910 unsigned long flags;
911
912 local_irq_save(flags);
913
914 bfin_write_MDMA_D0_START_ADDR(buf);
915 bfin_write_MDMA_D0_X_COUNT(len);
916 bfin_write_MDMA_D0_X_MODIFY(4);
917 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
918
919 bfin_write_MDMA_S0_START_ADDR(addr);
920 bfin_write_MDMA_S0_X_COUNT(len);
921 bfin_write_MDMA_S0_X_MODIFY(0);
922 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
923
924 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32);
925 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32);
926
927 blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len);
928
929 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
930
931 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
932
933 bfin_write_MDMA_S0_CONFIG(0);
934 bfin_write_MDMA_D0_CONFIG(0);
935 local_irq_restore(flags);
936
937}
938EXPORT_SYMBOL(dma_insl);
diff --git a/include/asm-blackfin/io.h b/include/asm-blackfin/io.h
index 7e6995e80d97..eac8bcaf64c2 100644
--- a/include/asm-blackfin/io.h
+++ b/include/asm-blackfin/io.h
@@ -115,13 +115,21 @@ static inline unsigned int readl(void __iomem *addr)
115 115
116#ifndef __ASSEMBLY__ 116#ifndef __ASSEMBLY__
117 117
118extern void outsb(void __iomem *port, const void *addr, unsigned long count); 118extern void outsb(void __iomem *port, const void *addr, unsigned short count);
119extern void outsw(void __iomem *port, const void *addr, unsigned long count); 119extern void outsw(void __iomem *port, const void *addr, unsigned short count);
120extern void outsl(void __iomem *port, const void *addr, unsigned long count); 120extern void outsl(void __iomem *port, const void *addr, unsigned short count);
121 121
122extern void insb(const void __iomem *port, void *addr, unsigned long count); 122extern void insb(const void __iomem *port, void *addr, unsigned short count);
123extern void insw(const void __iomem *port, void *addr, unsigned long count); 123extern void insw(const void __iomem *port, void *addr, unsigned short count);
124extern void insl(const void __iomem *port, void *addr, unsigned long count); 124extern void insl(const void __iomem *port, void *addr, unsigned short count);
125
126extern void dma_outsb(void __iomem *port, const void *addr, unsigned short count);
127extern void dma_outsw(void __iomem *port, const void *addr, unsigned short count);
128extern void dma_outsl(void __iomem *port, const void *addr, unsigned short count);
129
130extern void dma_insb(const void __iomem *port, void *addr, unsigned short count);
131extern void dma_insw(const void __iomem *port, void *addr, unsigned short count);
132extern void dma_insl(const void __iomem *port, void *addr, unsigned short count);
125 133
126/* 134/*
127 * Map some physical address range into the kernel address space. 135 * Map some physical address range into the kernel address space.