Merge branch 'dev' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
[pandora-kernel.git] / arch / avr32 / mm / dma-coherent.c
1 /*
2  *  Copyright (C) 2004-2006 Atmel Corporation
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 #include <linux/dma-mapping.h>
10 #include <linux/gfp.h>
11 #include <linux/export.h>
12
13 #include <asm/addrspace.h>
14 #include <asm/cacheflush.h>
15
16 void dma_cache_sync(struct device *dev, void *vaddr, size_t size, int direction)
17 {
18         /*
19          * No need to sync an uncached area
20          */
21         if (PXSEG(vaddr) == P2SEG)
22                 return;
23
24         switch (direction) {
25         case DMA_FROM_DEVICE:           /* invalidate only */
26                 invalidate_dcache_region(vaddr, size);
27                 break;
28         case DMA_TO_DEVICE:             /* writeback only */
29                 clean_dcache_region(vaddr, size);
30                 break;
31         case DMA_BIDIRECTIONAL:         /* writeback and invalidate */
32                 flush_dcache_region(vaddr, size);
33                 break;
34         default:
35                 BUG();
36         }
37 }
38 EXPORT_SYMBOL(dma_cache_sync);
39
40 static struct page *__dma_alloc(struct device *dev, size_t size,
41                                 dma_addr_t *handle, gfp_t gfp)
42 {
43         struct page *page, *free, *end;
44         int order;
45
46         /* Following is a work-around (a.k.a. hack) to prevent pages
47          * with __GFP_COMP being passed to split_page() which cannot
48          * handle them.  The real problem is that this flag probably
49          * should be 0 on AVR32 as it is not supported on this
50          * platform--see CONFIG_HUGETLB_PAGE. */
51         gfp &= ~(__GFP_COMP);
52
53         size = PAGE_ALIGN(size);
54         order = get_order(size);
55
56         page = alloc_pages(gfp, order);
57         if (!page)
58                 return NULL;
59         split_page(page, order);
60
61         /*
62          * When accessing physical memory with valid cache data, we
63          * get a cache hit even if the virtual memory region is marked
64          * as uncached.
65          *
66          * Since the memory is newly allocated, there is no point in
67          * doing a writeback. If the previous owner cares, he should
68          * have flushed the cache before releasing the memory.
69          */
70         invalidate_dcache_region(phys_to_virt(page_to_phys(page)), size);
71
72         *handle = page_to_bus(page);
73         free = page + (size >> PAGE_SHIFT);
74         end = page + (1 << order);
75
76         /*
77          * Free any unused pages
78          */
79         while (free < end) {
80                 __free_page(free);
81                 free++;
82         }
83
84         return page;
85 }
86
87 static void __dma_free(struct device *dev, size_t size,
88                        struct page *page, dma_addr_t handle)
89 {
90         struct page *end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
91
92         while (page < end)
93                 __free_page(page++);
94 }
95
96 void *dma_alloc_coherent(struct device *dev, size_t size,
97                          dma_addr_t *handle, gfp_t gfp)
98 {
99         struct page *page;
100         void *ret = NULL;
101
102         page = __dma_alloc(dev, size, handle, gfp);
103         if (page)
104                 ret = phys_to_uncached(page_to_phys(page));
105
106         return ret;
107 }
108 EXPORT_SYMBOL(dma_alloc_coherent);
109
110 void dma_free_coherent(struct device *dev, size_t size,
111                        void *cpu_addr, dma_addr_t handle)
112 {
113         void *addr = phys_to_cached(uncached_to_phys(cpu_addr));
114         struct page *page;
115
116         pr_debug("dma_free_coherent addr %p (phys %08lx) size %u\n",
117                  cpu_addr, (unsigned long)handle, (unsigned)size);
118         BUG_ON(!virt_addr_valid(addr));
119         page = virt_to_page(addr);
120         __dma_free(dev, size, page, handle);
121 }
122 EXPORT_SYMBOL(dma_free_coherent);
123
124 void *dma_alloc_writecombine(struct device *dev, size_t size,
125                              dma_addr_t *handle, gfp_t gfp)
126 {
127         struct page *page;
128         dma_addr_t phys;
129
130         page = __dma_alloc(dev, size, handle, gfp);
131         if (!page)
132                 return NULL;
133
134         phys = page_to_phys(page);
135         *handle = phys;
136
137         /* Now, map the page into P3 with write-combining turned on */
138         return __ioremap(phys, size, _PAGE_BUFFER);
139 }
140 EXPORT_SYMBOL(dma_alloc_writecombine);
141
142 void dma_free_writecombine(struct device *dev, size_t size,
143                            void *cpu_addr, dma_addr_t handle)
144 {
145         struct page *page;
146
147         iounmap(cpu_addr);
148
149         page = phys_to_page(handle);
150         __dma_free(dev, size, page, handle);
151 }
152 EXPORT_SYMBOL(dma_free_writecombine);