1 /* 2 * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> 3 * Copyright (C) 2009 Wind River Systems Inc 4 * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com 5 * 6 * Based on DMA code from MIPS. 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file "COPYING" in the main directory of this archive 10 * for more details. 11 */ 12 13 #include <linux/types.h> 14 #include <linux/mm.h> 15 #include <linux/string.h> 16 #include <linux/dma-mapping.h> 17 #include <linux/io.h> 18 #include <linux/cache.h> 19 #include <asm/cacheflush.h> 20 21 void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr, 22 size_t size, enum dma_data_direction dir) 23 { 24 void *vaddr = phys_to_virt(paddr); 25 26 switch (dir) { 27 case DMA_FROM_DEVICE: 28 invalidate_dcache_range((unsigned long)vaddr, 29 (unsigned long)(vaddr + size)); 30 break; 31 case DMA_TO_DEVICE: 32 /* 33 * We just need to flush the caches here , but Nios2 flush 34 * instruction will do both writeback and invalidate. 35 */ 36 case DMA_BIDIRECTIONAL: /* flush and invalidate */ 37 flush_dcache_range((unsigned long)vaddr, 38 (unsigned long)(vaddr + size)); 39 break; 40 default: 41 BUG(); 42 } 43 } 44 45 void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr, 46 size_t size, enum dma_data_direction dir) 47 { 48 void *vaddr = phys_to_virt(paddr); 49 50 switch (dir) { 51 case DMA_BIDIRECTIONAL: 52 case DMA_FROM_DEVICE: 53 invalidate_dcache_range((unsigned long)vaddr, 54 (unsigned long)(vaddr + size)); 55 break; 56 case DMA_TO_DEVICE: 57 break; 58 default: 59 BUG(); 60 } 61 } 62 63 void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, 64 gfp_t gfp, unsigned long attrs) 65 { 66 void *ret; 67 68 /* optimized page clearing */ 69 gfp |= __GFP_ZERO; 70 71 if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) 72 gfp |= GFP_DMA; 73 74 ret = (void *) __get_free_pages(gfp, get_order(size)); 75 if (ret != NULL) { 76 *dma_handle = virt_to_phys(ret); 77 flush_dcache_range((unsigned long) ret, 78 (unsigned long) ret + size); 79 ret = UNCAC_ADDR(ret); 80 } 81 82 return ret; 83 } 84 85 void arch_dma_free(struct device *dev, size_t size, void *vaddr, 86 dma_addr_t dma_handle, unsigned long attrs) 87 { 88 unsigned long addr = (unsigned long) CAC_ADDR((unsigned long) vaddr); 89 90 free_pages(addr, get_order(size)); 91 } 92