summaryrefslogtreecommitdiffstats
path: root/arch/nios2/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/nios2/mm')
-rw-r--r--arch/nios2/mm/cacheflush.c24
-rw-r--r--arch/nios2/mm/dma-mapping.c149
2 files changed, 84 insertions, 89 deletions
diff --git a/arch/nios2/mm/cacheflush.c b/arch/nios2/mm/cacheflush.c
index 223cdcc8203f..87bf88ed04c6 100644
--- a/arch/nios2/mm/cacheflush.c
+++ b/arch/nios2/mm/cacheflush.c
@@ -23,22 +23,6 @@ static void __flush_dcache(unsigned long start, unsigned long end)
end += (cpuinfo.dcache_line_size - 1);
end &= ~(cpuinfo.dcache_line_size - 1);
- for (addr = start; addr < end; addr += cpuinfo.dcache_line_size) {
- __asm__ __volatile__ (" flushda 0(%0)\n"
- : /* Outputs */
- : /* Inputs */ "r"(addr)
- /* : No clobber */);
- }
-}
-
-static void __flush_dcache_all(unsigned long start, unsigned long end)
-{
- unsigned long addr;
-
- start &= ~(cpuinfo.dcache_line_size - 1);
- end += (cpuinfo.dcache_line_size - 1);
- end &= ~(cpuinfo.dcache_line_size - 1);
-
if (end > start + cpuinfo.dcache_size)
end = start + cpuinfo.dcache_size;
@@ -112,7 +96,7 @@ static void flush_aliases(struct address_space *mapping, struct page *page)
void flush_cache_all(void)
{
- __flush_dcache_all(0, cpuinfo.dcache_size);
+ __flush_dcache(0, cpuinfo.dcache_size);
__flush_icache(0, cpuinfo.icache_size);
}
@@ -182,7 +166,7 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
*/
unsigned long start = (unsigned long)page_address(page);
- __flush_dcache_all(start, start + PAGE_SIZE);
+ __flush_dcache(start, start + PAGE_SIZE);
}
void flush_dcache_page(struct page *page)
@@ -268,7 +252,7 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
{
flush_cache_page(vma, user_vaddr, page_to_pfn(page));
memcpy(dst, src, len);
- __flush_dcache_all((unsigned long)src, (unsigned long)src + len);
+ __flush_dcache((unsigned long)src, (unsigned long)src + len);
if (vma->vm_flags & VM_EXEC)
__flush_icache((unsigned long)src, (unsigned long)src + len);
}
@@ -279,7 +263,7 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
{
flush_cache_page(vma, user_vaddr, page_to_pfn(page));
memcpy(dst, src, len);
- __flush_dcache_all((unsigned long)dst, (unsigned long)dst + len);
+ __flush_dcache((unsigned long)dst, (unsigned long)dst + len);
if (vma->vm_flags & VM_EXEC)
__flush_icache((unsigned long)dst, (unsigned long)dst + len);
}
diff --git a/arch/nios2/mm/dma-mapping.c b/arch/nios2/mm/dma-mapping.c
index ac5da7594f0b..90422c367ed3 100644
--- a/arch/nios2/mm/dma-mapping.c
+++ b/arch/nios2/mm/dma-mapping.c
@@ -20,9 +20,46 @@
#include <linux/cache.h>
#include <asm/cacheflush.h>
+static inline void __dma_sync_for_device(void *vaddr, size_t size,
+ enum dma_data_direction direction)
+{
+ switch (direction) {
+ case DMA_FROM_DEVICE:
+ invalidate_dcache_range((unsigned long)vaddr,
+ (unsigned long)(vaddr + size));
+ break;
+ case DMA_TO_DEVICE:
+ /*
+ * We just need to flush the caches here , but Nios2 flush
+ * instruction will do both writeback and invalidate.
+ */
+ case DMA_BIDIRECTIONAL: /* flush and invalidate */
+ flush_dcache_range((unsigned long)vaddr,
+ (unsigned long)(vaddr + size));
+ break;
+ default:
+ BUG();
+ }
+}
-void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+static inline void __dma_sync_for_cpu(void *vaddr, size_t size,
+ enum dma_data_direction direction)
+{
+ switch (direction) {
+ case DMA_BIDIRECTIONAL:
+ case DMA_FROM_DEVICE:
+ invalidate_dcache_range((unsigned long)vaddr,
+ (unsigned long)(vaddr + size));
+ break;
+ case DMA_TO_DEVICE:
+ break;
+ default:
+ BUG();
+ }
+}
+
+static void *nios2_dma_alloc(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
{
void *ret;
@@ -45,24 +82,21 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
return ret;
}
-EXPORT_SYMBOL(dma_alloc_coherent);
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
+static void nios2_dma_free(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle, struct dma_attrs *attrs)
{
unsigned long addr = (unsigned long) CAC_ADDR((unsigned long) vaddr);
free_pages(addr, get_order(size));
}
-EXPORT_SYMBOL(dma_free_coherent);
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction direction)
+static int nios2_dma_map_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
int i;
- BUG_ON(!valid_dma_direction(direction));
-
for_each_sg(sg, sg, nents, i) {
void *addr;
@@ -75,40 +109,32 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
return nents;
}
-EXPORT_SYMBOL(dma_map_sg);
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
+static dma_addr_t nios2_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
- void *addr;
-
- BUG_ON(!valid_dma_direction(direction));
+ void *addr = page_address(page) + offset;
- addr = page_address(page) + offset;
__dma_sync_for_device(addr, size, direction);
-
return page_to_phys(page) + offset;
}
-EXPORT_SYMBOL(dma_map_page);
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
- enum dma_data_direction direction)
+static void nios2_dma_unmap_page(struct device *dev, dma_addr_t dma_address,
+ size_t size, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
- BUG_ON(!valid_dma_direction(direction));
-
__dma_sync_for_cpu(phys_to_virt(dma_address), size, direction);
}
-EXPORT_SYMBOL(dma_unmap_page);
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
- enum dma_data_direction direction)
+static void nios2_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+ int nhwentries, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
void *addr;
int i;
- BUG_ON(!valid_dma_direction(direction));
-
if (direction == DMA_TO_DEVICE)
return;
@@ -118,69 +144,54 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
__dma_sync_for_cpu(addr, sg->length, direction);
}
}
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction direction)
-{
- BUG_ON(!valid_dma_direction(direction));
- __dma_sync_for_cpu(phys_to_virt(dma_handle), size, direction);
-}
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction direction)
-{
- BUG_ON(!valid_dma_direction(direction));
-
- __dma_sync_for_device(phys_to_virt(dma_handle), size, direction);
-}
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
+static void nios2_dma_sync_single_for_cpu(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
{
- BUG_ON(!valid_dma_direction(direction));
-
__dma_sync_for_cpu(phys_to_virt(dma_handle), size, direction);
}
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
+static void nios2_dma_sync_single_for_device(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
{
- BUG_ON(!valid_dma_direction(direction));
-
__dma_sync_for_device(phys_to_virt(dma_handle), size, direction);
}
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
- enum dma_data_direction direction)
+static void nios2_dma_sync_sg_for_cpu(struct device *dev,
+ struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
{
int i;
- BUG_ON(!valid_dma_direction(direction));
-
/* Make sure that gcc doesn't leave the empty loop body. */
for_each_sg(sg, sg, nelems, i)
__dma_sync_for_cpu(sg_virt(sg), sg->length, direction);
}
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
- int nelems, enum dma_data_direction direction)
+static void nios2_dma_sync_sg_for_device(struct device *dev,
+ struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
{
int i;
- BUG_ON(!valid_dma_direction(direction));
-
/* Make sure that gcc doesn't leave the empty loop body. */
for_each_sg(sg, sg, nelems, i)
__dma_sync_for_device(sg_virt(sg), sg->length, direction);
}
-EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+struct dma_map_ops nios2_dma_ops = {
+ .alloc = nios2_dma_alloc,
+ .free = nios2_dma_free,
+ .map_page = nios2_dma_map_page,
+ .unmap_page = nios2_dma_unmap_page,
+ .map_sg = nios2_dma_map_sg,
+ .unmap_sg = nios2_dma_unmap_sg,
+ .sync_single_for_device = nios2_dma_sync_single_for_device,
+ .sync_single_for_cpu = nios2_dma_sync_single_for_cpu,
+ .sync_sg_for_cpu = nios2_dma_sync_sg_for_cpu,
+ .sync_sg_for_device = nios2_dma_sync_sg_for_device,
+};
+EXPORT_SYMBOL(nios2_dma_ops);
OpenPOWER on IntegriCloud