diff options
author | Michael Hennerich <michael.hennerich@analog.com> | 2007-05-21 06:09:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-21 12:50:22 -0400 |
commit | 23ee968d96ef5ad564c0f0b8a30412fb93137ebb (patch) | |
tree | a323c73062fa32a794e254a39c519650f0efe4b9 | |
parent | d1b945fdb62f3e6852fea5a8779c0151ac1e55a8 (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.c | 204 | ||||
-rw-r--r-- | include/asm-blackfin/io.h | 20 |
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 | ||
733 | void *safe_dma_memcpy(void *dest, const void *src, size_t size) | 739 | void *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 | } |
742 | EXPORT_SYMBOL(safe_dma_memcpy); | 745 | EXPORT_SYMBOL(safe_dma_memcpy); |
746 | |||
747 | void 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 | } | ||
778 | EXPORT_SYMBOL(dma_outsb); | ||
779 | |||
780 | |||
781 | void 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 | } | ||
810 | EXPORT_SYMBOL(dma_insb); | ||
811 | |||
812 | void 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 | } | ||
842 | EXPORT_SYMBOL(dma_outsw); | ||
843 | |||
844 | void 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 | } | ||
874 | EXPORT_SYMBOL(dma_insw); | ||
875 | |||
876 | void 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 | } | ||
906 | EXPORT_SYMBOL(dma_outsl); | ||
907 | |||
908 | void 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 | } | ||
938 | EXPORT_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 | ||
118 | extern void outsb(void __iomem *port, const void *addr, unsigned long count); | 118 | extern void outsb(void __iomem *port, const void *addr, unsigned short count); |
119 | extern void outsw(void __iomem *port, const void *addr, unsigned long count); | 119 | extern void outsw(void __iomem *port, const void *addr, unsigned short count); |
120 | extern void outsl(void __iomem *port, const void *addr, unsigned long count); | 120 | extern void outsl(void __iomem *port, const void *addr, unsigned short count); |
121 | 121 | ||
122 | extern void insb(const void __iomem *port, void *addr, unsigned long count); | 122 | extern void insb(const void __iomem *port, void *addr, unsigned short count); |
123 | extern void insw(const void __iomem *port, void *addr, unsigned long count); | 123 | extern void insw(const void __iomem *port, void *addr, unsigned short count); |
124 | extern void insl(const void __iomem *port, void *addr, unsigned long count); | 124 | extern void insl(const void __iomem *port, void *addr, unsigned short count); |
125 | |||
126 | extern void dma_outsb(void __iomem *port, const void *addr, unsigned short count); | ||
127 | extern void dma_outsw(void __iomem *port, const void *addr, unsigned short count); | ||
128 | extern void dma_outsl(void __iomem *port, const void *addr, unsigned short count); | ||
129 | |||
130 | extern void dma_insb(const void __iomem *port, void *addr, unsigned short count); | ||
131 | extern void dma_insw(const void __iomem *port, void *addr, unsigned short count); | ||
132 | extern 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. |