xref: /openbmc/linux/arch/arc/mm/dma.c (revision 1162b070)
11162b070SVineet Gupta /*
21162b070SVineet Gupta  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
31162b070SVineet Gupta  *
41162b070SVineet Gupta  * This program is free software; you can redistribute it and/or modify
51162b070SVineet Gupta  * it under the terms of the GNU General Public License version 2 as
61162b070SVineet Gupta  * published by the Free Software Foundation.
71162b070SVineet Gupta  */
81162b070SVineet Gupta 
91162b070SVineet Gupta /*
101162b070SVineet Gupta  * DMA Coherent API Notes
111162b070SVineet Gupta  *
121162b070SVineet Gupta  * I/O is inherently non-coherent on ARC. So a coherent DMA buffer is
131162b070SVineet Gupta  * implemented by accessintg it using a kernel virtual address, with
141162b070SVineet Gupta  * Cache bit off in the TLB entry.
151162b070SVineet Gupta  *
161162b070SVineet Gupta  * The default DMA address == Phy address which is 0x8000_0000 based.
171162b070SVineet Gupta  * A platform/device can make it zero based, by over-riding
181162b070SVineet Gupta  * plat_{dma,kernel}_addr_to_{kernel,dma}
191162b070SVineet Gupta  */
201162b070SVineet Gupta 
211162b070SVineet Gupta #include <linux/dma-mapping.h>
221162b070SVineet Gupta #include <linux/dma-debug.h>
231162b070SVineet Gupta #include <linux/export.h>
241162b070SVineet Gupta #include <asm/cacheflush.h>
251162b070SVineet Gupta 
261162b070SVineet Gupta /*
271162b070SVineet Gupta  * Helpers for Coherent DMA API.
281162b070SVineet Gupta  */
291162b070SVineet Gupta void *dma_alloc_noncoherent(struct device *dev, size_t size,
301162b070SVineet Gupta 			    dma_addr_t *dma_handle, gfp_t gfp)
311162b070SVineet Gupta {
321162b070SVineet Gupta 	void *paddr;
331162b070SVineet Gupta 
341162b070SVineet Gupta 	/* This is linear addr (0x8000_0000 based) */
351162b070SVineet Gupta 	paddr = alloc_pages_exact(size, gfp);
361162b070SVineet Gupta 	if (!paddr)
371162b070SVineet Gupta 		return NULL;
381162b070SVineet Gupta 
391162b070SVineet Gupta 	/* This is bus address, platform dependent */
401162b070SVineet Gupta 	*dma_handle = plat_kernel_addr_to_dma(dev, paddr);
411162b070SVineet Gupta 
421162b070SVineet Gupta 	return paddr;
431162b070SVineet Gupta }
441162b070SVineet Gupta EXPORT_SYMBOL(dma_alloc_noncoherent);
451162b070SVineet Gupta 
461162b070SVineet Gupta void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
471162b070SVineet Gupta 			  dma_addr_t dma_handle)
481162b070SVineet Gupta {
491162b070SVineet Gupta 	free_pages_exact((void *)plat_dma_addr_to_kernel(dev, dma_handle),
501162b070SVineet Gupta 			 size);
511162b070SVineet Gupta }
521162b070SVineet Gupta EXPORT_SYMBOL(dma_free_noncoherent);
531162b070SVineet Gupta 
541162b070SVineet Gupta void *dma_alloc_coherent(struct device *dev, size_t size,
551162b070SVineet Gupta 			 dma_addr_t *dma_handle, gfp_t gfp)
561162b070SVineet Gupta {
571162b070SVineet Gupta 	void *paddr, *kvaddr;
581162b070SVineet Gupta 
591162b070SVineet Gupta 	/* This is linear addr (0x8000_0000 based) */
601162b070SVineet Gupta 	paddr = alloc_pages_exact(size, gfp);
611162b070SVineet Gupta 	if (!paddr)
621162b070SVineet Gupta 		return NULL;
631162b070SVineet Gupta 
641162b070SVineet Gupta 	/* This is kernel Virtual address (0x7000_0000 based) */
651162b070SVineet Gupta 	kvaddr = ioremap_nocache((unsigned long)paddr, size);
661162b070SVineet Gupta 	if (kvaddr != NULL)
671162b070SVineet Gupta 		memset(kvaddr, 0, size);
681162b070SVineet Gupta 
691162b070SVineet Gupta 	/* This is bus address, platform dependent */
701162b070SVineet Gupta 	*dma_handle = plat_kernel_addr_to_dma(dev, paddr);
711162b070SVineet Gupta 
721162b070SVineet Gupta 	return kvaddr;
731162b070SVineet Gupta }
741162b070SVineet Gupta EXPORT_SYMBOL(dma_alloc_coherent);
751162b070SVineet Gupta 
761162b070SVineet Gupta void dma_free_coherent(struct device *dev, size_t size, void *kvaddr,
771162b070SVineet Gupta 		       dma_addr_t dma_handle)
781162b070SVineet Gupta {
791162b070SVineet Gupta 	iounmap((void __force __iomem *)kvaddr);
801162b070SVineet Gupta 
811162b070SVineet Gupta 	free_pages_exact((void *)plat_dma_addr_to_kernel(dev, dma_handle),
821162b070SVineet Gupta 			 size);
831162b070SVineet Gupta }
841162b070SVineet Gupta EXPORT_SYMBOL(dma_free_coherent);
851162b070SVineet Gupta 
861162b070SVineet Gupta /*
871162b070SVineet Gupta  * Helper for streaming DMA...
881162b070SVineet Gupta  */
891162b070SVineet Gupta void __arc_dma_cache_sync(unsigned long paddr, size_t size,
901162b070SVineet Gupta 			  enum dma_data_direction dir)
911162b070SVineet Gupta {
921162b070SVineet Gupta 	__inline_dma_cache_sync(paddr, size, dir);
931162b070SVineet Gupta }
941162b070SVineet Gupta EXPORT_SYMBOL(__arc_dma_cache_sync);
95