diff options
Diffstat (limited to 'arch/arm/cpu/mmu.c')
-rw-r--r-- | arch/arm/cpu/mmu.c | 55 |
1 files changed, 37 insertions, 18 deletions
diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c index 299ebdb51c..37bfa058a5 100644 --- a/arch/arm/cpu/mmu.c +++ b/arch/arm/cpu/mmu.c @@ -18,6 +18,7 @@ #define pr_fmt(fmt) "mmu: " fmt #include <common.h> +#include <dma-dir.h> #include <init.h> #include <asm/mmu.h> #include <errno.h> @@ -156,6 +157,20 @@ static u32 *find_pte(unsigned long adr) return &table[(adr >> PAGE_SHIFT) & 0xff]; } +static void dma_flush_range(unsigned long start, unsigned long end) +{ + if (outer_cache.flush_range) + outer_cache.flush_range(start, end); + __dma_flush_range(start, end); +} + +static void dma_inv_range(unsigned long start, unsigned long end) +{ + if (outer_cache.inv_range) + outer_cache.inv_range(start, end); + __dma_inv_range(start, end); +} + void remap_range(void *_start, size_t size, uint32_t flags) { unsigned long start = (unsigned long)_start; @@ -377,12 +392,14 @@ static int mmu_init(void) } mmu_initcall(mmu_init); -void *dma_alloc_coherent(size_t size) +void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle) { void *ret; size = PAGE_ALIGN(size); ret = xmemalign(PAGE_SIZE, size); + if (dma_handle) + *dma_handle = (dma_addr_t)ret; dma_inv_range((unsigned long)ret, (unsigned long)ret + size); @@ -401,7 +418,7 @@ void *phys_to_virt(unsigned long phys) return (void *)phys; } -void dma_free_coherent(void *mem, size_t size) +void dma_free_coherent(void *mem, dma_addr_t dma_handle, size_t size) { size = PAGE_ALIGN(size); remap_range(mem, size, pte_flags_cached); @@ -409,24 +426,26 @@ void dma_free_coherent(void *mem, size_t size) free(mem); } -void dma_clean_range(unsigned long start, unsigned long end) +void dma_sync_single_for_cpu(unsigned long address, size_t size, + enum dma_data_direction dir) { - if (outer_cache.clean_range) - outer_cache.clean_range(start, end); - __dma_clean_range(start, end); -} - -void dma_flush_range(unsigned long start, unsigned long end) -{ - if (outer_cache.flush_range) - outer_cache.flush_range(start, end); - __dma_flush_range(start, end); + if (dir != DMA_TO_DEVICE) { + if (outer_cache.inv_range) + outer_cache.inv_range(address, address + size); + __dma_inv_range(address, address + size); + } } -void dma_inv_range(unsigned long start, unsigned long end) +void dma_sync_single_for_device(unsigned long address, size_t size, + enum dma_data_direction dir) { - if (outer_cache.inv_range) - outer_cache.inv_range(start, end); - __dma_inv_range(start, end); + if (dir == DMA_FROM_DEVICE) { + __dma_inv_range(address, address + size); + if (outer_cache.inv_range) + outer_cache.inv_range(address, address + size); + } else { + __dma_clean_range(address, address + size); + if (outer_cache.clean_range) + outer_cache.clean_range(address, address + size); + } } - |