2.6.31 support (WiP)
[oweals/openwrt.git] / target / linux / coldfire / files-2.6.31 / arch / m68k / include / asm / cf_548x_cacheflush.h
1 /*
2  * arch/m68k/include/asm/cf_548x_cacheflush.h - Coldfire 547x/548x Cache
3  *
4  * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved.
5  * Kurt Mahan kmahan@freescale.com
6  * Shrek Wu b16972@freescale.com
7  *
8  * Based on include/asm-m68k/cacheflush.h
9  *
10  * This program is free software; you can redistribute  it and/or modify it
11  * under  the terms of  the GNU General  Public License as published by the
12  * Free Software Foundation;  either version 2 of the  License, or (at your
13  * option) any later version.
14  */
15 #ifndef M68K_CF_548x_CACHEFLUSH_H
16 #define M68K_CF_548x_CACHEFLUSH_H
17
18 #include <asm/cfcache.h>
19 /*
20  * Cache handling functions
21  */
22
23 #define flush_icache()                                          \
24 ({                                                              \
25         unsigned long set;                                      \
26         unsigned long start_set;                                \
27         unsigned long end_set;                                  \
28                                                                 \
29         start_set = 0;                                          \
30         end_set = (unsigned long)LAST_DCACHE_ADDR;              \
31                                                                 \
32         for (set = start_set; set <= end_set; set += (0x10 - 3)) {\
33                 asm volatile("cpushl %%ic,(%0)\n"               \
34                 "\taddq%.l #1,%0\n"                             \
35                 "\tcpushl %%ic,(%0)\n"                          \
36                 "\taddq%.l #1,%0\n"                             \
37                 "\tcpushl %%ic,(%0)\n"                          \
38                 "\taddq%.l #1,%0\n"                             \
39                 "\tcpushl %%ic,(%0)" : "=a" (set) : "a" (set)); \
40         }                                                       \
41 })
42
43 #define flush_dcache()                                          \
44 ({                                                              \
45         unsigned long set;                                      \
46         unsigned long start_set;                                \
47         unsigned long end_set;                                  \
48                                                                 \
49         start_set = 0;                                          \
50         end_set = (unsigned long)LAST_DCACHE_ADDR;              \
51                                                                 \
52         for (set = start_set; set <= end_set; set += (0x10 - 3)) {      \
53                 asm volatile("cpushl %%dc,(%0)\n"               \
54                 "\taddq%.l #1,%0\n"                             \
55                 "\tcpushl %%dc,(%0)\n"                          \
56                 "\taddq%.l #1,%0\n"                             \
57                 "\tcpushl %%dc,(%0)\n"                          \
58                 "\taddq%.l #1,%0\n"                             \
59                 "\tcpushl %%dc,(%0)" : "=a" (set) : "a" (set)); \
60         }                                                       \
61 })
62
63 #define flush_bcache()                                          \
64 ({                                                      \
65         unsigned long set;                              \
66         unsigned long start_set;                        \
67         unsigned long end_set;                          \
68                                                         \
69         start_set = 0;                                  \
70         end_set = (unsigned long)LAST_DCACHE_ADDR;      \
71                                                         \
72         for (set = start_set; set <= end_set; set += (0x10 - 3)) { \
73                 asm volatile("cpushl %%bc,(%0)\n"               \
74                 "\taddq%.l #1,%0\n"                             \
75                 "\tcpushl %%bc,(%0)\n"                          \
76                 "\taddq%.l #1,%0\n"                             \
77                 "\tcpushl %%bc,(%0)\n"                          \
78                 "\taddq%.l #1,%0\n"                             \
79                 "\tcpushl %%bc,(%0)" : "=a" (set) : "a" (set)); \
80         }                                                       \
81 })
82
83 /*
84  * invalidate the cache for the specified memory range.
85  * It starts at the physical address specified for
86  * the given number of bytes.
87  */
88 extern void cache_clear(unsigned long paddr, int len);
89 /*
90  * push any dirty cache in the specified memory range.
91  * It starts at the physical address specified for
92  * the given number of bytes.
93  */
94 extern void cache_push(unsigned long paddr, int len);
95
96 /*
97  * push and invalidate pages in the specified user virtual
98  * memory range.
99  */
100 extern void cache_push_v(unsigned long vaddr, int len);
101
102 /* This is needed whenever the virtual mapping of the current
103    process changes.  */
104
105 /**
106  * flush_cache_mm - Flush an mm_struct
107  * @mm: mm_struct to flush
108  */
109 static inline void flush_cache_mm(struct mm_struct *mm)
110 {
111         if (mm == current->mm)
112                 flush_bcache();
113 }
114
115 #define flush_cache_dup_mm(mm)  flush_cache_mm(mm)
116
117 #define flush_cache_all()               flush_bcache()
118
119 /**
120  * flush_cache_range - Flush a cache range
121  * @vma: vma struct
122  * @start: Starting address
123  * @end: Ending address
124  *
125  * flush_cache_range must be a macro to avoid a dependency on
126  * linux/mm.h which includes this file.
127  */
128 static inline void flush_cache_range(struct vm_area_struct *vma,
129         unsigned long start, unsigned long end)
130 {
131         if (vma->vm_mm == current->mm)
132                 flush_bcache();
133 /*cf_cache_flush_range(start, end);*/
134 }
135
136 /**
137  * flush_cache_page - Flush a page of the cache
138  * @vma: vma struct
139  * @vmaddr:
140  * @pfn: page numer
141  *
142  * flush_cache_page must be a macro to avoid a dependency on
143  * linux/mm.h which includes this file.
144  */
145 static inline void flush_cache_page(struct vm_area_struct *vma,
146         unsigned long vmaddr, unsigned long pfn)
147 {
148         if (vma->vm_mm == current->mm)
149                 flush_bcache();
150 /*cf_cache_flush_range(vmaddr, vmaddr+PAGE_SIZE);*/
151 }
152
153 /* Push the page at kernel virtual address and clear the icache */
154 /* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
155 #define flush_page_to_ram(page) __flush_page_to_ram((void *) page_address(page))
156 extern inline void __flush_page_to_ram(void *address)
157 {
158         unsigned long set;
159         unsigned long start_set;
160         unsigned long end_set;
161         unsigned long addr = (unsigned long) address;
162
163         addr &= ~(PAGE_SIZE - 1);
164         /* round down to page start address */
165
166         start_set = addr & _ICACHE_SET_MASK;
167         end_set = (addr + PAGE_SIZE-1) & _ICACHE_SET_MASK;
168
169         if (start_set > end_set) {
170                 /* from the begining to the lowest address */
171                 for (set = 0; set <= end_set; set += (0x10 - 3)) {
172                         asm volatile("cpushl %%bc,(%0)\n"
173                         "\taddq%.l #1,%0\n"
174                         "\tcpushl %%bc,(%0)\n"
175                         "\taddq%.l #1,%0\n"
176                         "\tcpushl %%bc,(%0)\n"
177                         "\taddq%.l #1,%0\n"
178                         "\tcpushl %%bc,(%0)" : "=a" (set) : "a" (set));
179                 }
180                 /* next loop will finish the cache ie pass the hole */
181                 end_set = LAST_ICACHE_ADDR;
182         }
183
184         for (set = start_set; set <= end_set; set += (0x10 - 3)) {
185                 asm volatile("cpushl %%bc,(%0)\n"
186                 "\taddq%.l #1,%0\n"
187                 "\tcpushl %%bc,(%0)\n"
188                 "\taddq%.l #1,%0\n"
189                 "\tcpushl %%bc,(%0)\n"
190                 "\taddq%.l #1,%0\n"
191                 "\tcpushl %%bc,(%0)" : "=a" (set) : "a" (set));
192         }
193 }
194
195 /* Use __flush_page_to_ram() for flush_dcache_page all values are same - MW */
196 #define flush_dcache_page(page)                 \
197         __flush_page_to_ram((void *) page_address(page))
198 #define flush_icache_page(vma, pg)              \
199         __flush_page_to_ram((void *) page_address(pg))
200 #define flush_icache_user_range(adr, len)       \
201         do { } while (0)
202 /* NL */
203 #define flush_icache_user_page(vma, page, addr, len)    \
204         do { } while (0)
205
206 /* Push n pages at kernel virtual address and clear the icache */
207 /* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
208 extern inline void flush_icache_range(unsigned long address,
209         unsigned long endaddr)
210 {
211         unsigned long set;
212         unsigned long start_set;
213         unsigned long end_set;
214
215         start_set = address & _ICACHE_SET_MASK;
216         end_set = endaddr & _ICACHE_SET_MASK;
217
218         if (start_set > end_set) {
219                 /* from the begining to the lowest address */
220                 for (set = 0; set <= end_set; set += (0x10 - 3)) {
221                         asm volatile("cpushl %%ic,(%0)\n"
222                         "\taddq%.l #1,%0\n"
223                         "\tcpushl %%ic,(%0)\n"
224                         "\taddq%.l #1,%0\n"
225                         "\tcpushl %%ic,(%0)\n"
226                         "\taddq%.l #1,%0\n"
227                         "\tcpushl %%ic,(%0)" : "=a" (set) : "a" (set));
228                 }
229                 /* next loop will finish the cache ie pass the hole */
230                 end_set = LAST_ICACHE_ADDR;
231         }
232         for (set = start_set; set <= end_set; set += (0x10 - 3)) {
233                 asm volatile("cpushl %%ic,(%0)\n"
234                         "\taddq%.l #1,%0\n"
235                         "\tcpushl %%ic,(%0)\n"
236                         "\taddq%.l #1,%0\n"
237                         "\tcpushl %%ic,(%0)\n"
238                         "\taddq%.l #1,%0\n"
239                         "\tcpushl %%ic,(%0)" : "=a" (set) : "a" (set));
240         }
241 }
242
243 static inline void copy_to_user_page(struct vm_area_struct *vma,
244                                      struct page *page, unsigned long vaddr,
245                                      void *dst, void *src, int len)
246 {
247         memcpy(dst, src, len);
248         flush_icache_user_page(vma, page, vaddr, len);
249 }
250 static inline void copy_from_user_page(struct vm_area_struct *vma,
251                                        struct page *page, unsigned long vaddr,
252                                        void *dst, void *src, int len)
253 {
254         memcpy(dst, src, len);
255 }
256
257 #define flush_cache_vmap(start, end)            flush_cache_all()
258 #define flush_cache_vunmap(start, end)          flush_cache_all()
259 #define flush_dcache_mmap_lock(mapping)         do { } while (0)
260 #define flush_dcache_mmap_unlock(mapping)       do { } while (0)
261
262 #endif /* M68K_CF_548x_CACHEFLUSH_H */