1/* 2 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9/* 10 * DMA Coherent API Notes 11 * 12 * I/O is inherently non-coherent on ARC. So a coherent DMA buffer is 13 * implemented by accessintg it using a kernel virtual address, with 14 * Cache bit off in the TLB entry. 15 * 16 * The default DMA address == Phy address which is 0x8000_0000 based. 17 * A platform/device can make it zero based, by over-riding 18 * plat_{dma,kernel}_addr_to_{kernel,dma} 19 */ 20 21#include <linux/dma-mapping.h> 22#include <linux/dma-debug.h> 23#include <linux/export.h> 24#include <asm/cacheflush.h> 25 26/* 27 * Helpers for Coherent DMA API. 28 */ 29void *dma_alloc_noncoherent(struct device *dev, size_t size, 30 dma_addr_t *dma_handle, gfp_t gfp) 31{ 32 void *paddr; 33 34 /* This is linear addr (0x8000_0000 based) */ 35 paddr = alloc_pages_exact(size, gfp); 36 if (!paddr) 37 return NULL; 38 39 /* This is bus address, platform dependent */ 40 *dma_handle = plat_kernel_addr_to_dma(dev, paddr); 41 42 return paddr; 43} 44EXPORT_SYMBOL(dma_alloc_noncoherent); 45 46void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, 47 dma_addr_t dma_handle) 48{ 49 free_pages_exact((void *)plat_dma_addr_to_kernel(dev, dma_handle), 50 size); 51} 52EXPORT_SYMBOL(dma_free_noncoherent); 53 54void *dma_alloc_coherent(struct device *dev, size_t size, 55 dma_addr_t *dma_handle, gfp_t gfp) 56{ 57 void *paddr, *kvaddr; 58 59 /* This is linear addr (0x8000_0000 based) */ 60 paddr = alloc_pages_exact(size, gfp); 61 if (!paddr) 62 return NULL; 63 64 /* This is kernel Virtual address (0x7000_0000 based) */ 65 kvaddr = ioremap_nocache((unsigned long)paddr, size); 66 if (kvaddr != NULL) 67 memset(kvaddr, 0, size); 68 69 /* This is bus address, platform dependent */ 70 *dma_handle = plat_kernel_addr_to_dma(dev, paddr); 71 72 return kvaddr; 73} 74EXPORT_SYMBOL(dma_alloc_coherent); 75 76void dma_free_coherent(struct device *dev, size_t size, void *kvaddr, 77 dma_addr_t dma_handle) 78{ 79 iounmap((void __force __iomem *)kvaddr); 80 81 free_pages_exact((void *)plat_dma_addr_to_kernel(dev, dma_handle), 82 size); 83} 84EXPORT_SYMBOL(dma_free_coherent); 85 86/* 87 * Helper for streaming DMA... 88 */ 89void __arc_dma_cache_sync(unsigned long paddr, size_t size, 90 enum dma_data_direction dir) 91{ 92 __inline_dma_cache_sync(paddr, size, dir); 93} 94EXPORT_SYMBOL(__arc_dma_cache_sync); 95