diff options
Diffstat (limited to 'arch/arm/mm/cache-v6.S')
-rw-r--r-- | arch/arm/mm/cache-v6.S | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S new file mode 100644 index 000000000000..85c10a71e7c6 --- /dev/null +++ b/arch/arm/mm/cache-v6.S | |||
@@ -0,0 +1,227 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mm/cache-v6.S | ||
3 | * | ||
4 | * Copyright (C) 2001 Deep Blue Solutions Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This is the "shell" of the ARMv6 processor support. | ||
11 | */ | ||
12 | #include <linux/linkage.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <asm/assembler.h> | ||
15 | |||
16 | #include "proc-macros.S" | ||
17 | |||
18 | #define HARVARD_CACHE | ||
19 | #define CACHE_LINE_SIZE 32 | ||
20 | #define D_CACHE_LINE_SIZE 32 | ||
21 | |||
22 | /* | ||
23 | * v6_flush_cache_all() | ||
24 | * | ||
25 | * Flush the entire cache. | ||
26 | * | ||
27 | * It is assumed that: | ||
28 | */ | ||
29 | ENTRY(v6_flush_kern_cache_all) | ||
30 | mov r0, #0 | ||
31 | #ifdef HARVARD_CACHE | ||
32 | mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate | ||
33 | mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate | ||
34 | #else | ||
35 | mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate | ||
36 | #endif | ||
37 | mov pc, lr | ||
38 | |||
39 | /* | ||
40 | * v6_flush_cache_all() | ||
41 | * | ||
42 | * Flush all TLB entries in a particular address space | ||
43 | * | ||
44 | * - mm - mm_struct describing address space | ||
45 | */ | ||
46 | ENTRY(v6_flush_user_cache_all) | ||
47 | /*FALLTHROUGH*/ | ||
48 | |||
49 | /* | ||
50 | * v6_flush_cache_range(start, end, flags) | ||
51 | * | ||
52 | * Flush a range of TLB entries in the specified address space. | ||
53 | * | ||
54 | * - start - start address (may not be aligned) | ||
55 | * - end - end address (exclusive, may not be aligned) | ||
56 | * - flags - vm_area_struct flags describing address space | ||
57 | * | ||
58 | * It is assumed that: | ||
59 | * - we have a VIPT cache. | ||
60 | */ | ||
61 | ENTRY(v6_flush_user_cache_range) | ||
62 | mov pc, lr | ||
63 | |||
64 | /* | ||
65 | * v6_coherent_kern_range(start,end) | ||
66 | * | ||
67 | * Ensure that the I and D caches are coherent within specified | ||
68 | * region. This is typically used when code has been written to | ||
69 | * a memory region, and will be executed. | ||
70 | * | ||
71 | * - start - virtual start address of region | ||
72 | * - end - virtual end address of region | ||
73 | * | ||
74 | * It is assumed that: | ||
75 | * - the Icache does not read data from the write buffer | ||
76 | */ | ||
77 | ENTRY(v6_coherent_kern_range) | ||
78 | /* FALLTHROUGH */ | ||
79 | |||
80 | /* | ||
81 | * v6_coherent_user_range(start,end) | ||
82 | * | ||
83 | * Ensure that the I and D caches are coherent within specified | ||
84 | * region. This is typically used when code has been written to | ||
85 | * a memory region, and will be executed. | ||
86 | * | ||
87 | * - start - virtual start address of region | ||
88 | * - end - virtual end address of region | ||
89 | * | ||
90 | * It is assumed that: | ||
91 | * - the Icache does not read data from the write buffer | ||
92 | */ | ||
93 | ENTRY(v6_coherent_user_range) | ||
94 | bic r0, r0, #CACHE_LINE_SIZE - 1 | ||
95 | 1: | ||
96 | #ifdef HARVARD_CACHE | ||
97 | mcr p15, 0, r0, c7, c10, 1 @ clean D line | ||
98 | mcr p15, 0, r0, c7, c5, 1 @ invalidate I line | ||
99 | #endif | ||
100 | mcr p15, 0, r0, c7, c5, 7 @ invalidate BTB entry | ||
101 | add r0, r0, #CACHE_LINE_SIZE | ||
102 | cmp r0, r1 | ||
103 | blo 1b | ||
104 | #ifdef HARVARD_CACHE | ||
105 | mov r0, #0 | ||
106 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
107 | #endif | ||
108 | mov pc, lr | ||
109 | |||
110 | /* | ||
111 | * v6_flush_kern_dcache_page(kaddr) | ||
112 | * | ||
113 | * Ensure that the data held in the page kaddr is written back | ||
114 | * to the page in question. | ||
115 | * | ||
116 | * - kaddr - kernel address (guaranteed to be page aligned) | ||
117 | */ | ||
118 | ENTRY(v6_flush_kern_dcache_page) | ||
119 | add r1, r0, #PAGE_SZ | ||
120 | 1: | ||
121 | #ifdef HARVARD_CACHE | ||
122 | mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line | ||
123 | #else | ||
124 | mcr p15, 0, r0, c7, c15, 1 @ clean & invalidate unified line | ||
125 | #endif | ||
126 | add r0, r0, #D_CACHE_LINE_SIZE | ||
127 | cmp r0, r1 | ||
128 | blo 1b | ||
129 | #ifdef HARVARD_CACHE | ||
130 | mov r0, #0 | ||
131 | mcr p15, 0, r0, c7, c10, 4 | ||
132 | #endif | ||
133 | mov pc, lr | ||
134 | |||
135 | |||
136 | /* | ||
137 | * v6_dma_inv_range(start,end) | ||
138 | * | ||
139 | * Invalidate the data cache within the specified region; we will | ||
140 | * be performing a DMA operation in this region and we want to | ||
141 | * purge old data in the cache. | ||
142 | * | ||
143 | * - start - virtual start address of region | ||
144 | * - end - virtual end address of region | ||
145 | */ | ||
146 | ENTRY(v6_dma_inv_range) | ||
147 | tst r0, #D_CACHE_LINE_SIZE - 1 | ||
148 | bic r0, r0, #D_CACHE_LINE_SIZE - 1 | ||
149 | #ifdef HARVARD_CACHE | ||
150 | mcrne p15, 0, r0, c7, c10, 1 @ clean D line | ||
151 | #else | ||
152 | mcrne p15, 0, r0, c7, c11, 1 @ clean unified line | ||
153 | #endif | ||
154 | tst r1, #D_CACHE_LINE_SIZE - 1 | ||
155 | bic r1, r1, #D_CACHE_LINE_SIZE - 1 | ||
156 | #ifdef HARVARD_CACHE | ||
157 | mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D line | ||
158 | #else | ||
159 | mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line | ||
160 | #endif | ||
161 | 1: | ||
162 | #ifdef HARVARD_CACHE | ||
163 | mcr p15, 0, r0, c7, c6, 1 @ invalidate D line | ||
164 | #else | ||
165 | mcr p15, 0, r0, c7, c7, 1 @ invalidate unified line | ||
166 | #endif | ||
167 | add r0, r0, #D_CACHE_LINE_SIZE | ||
168 | cmp r0, r1 | ||
169 | blo 1b | ||
170 | mov r0, #0 | ||
171 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
172 | mov pc, lr | ||
173 | |||
174 | /* | ||
175 | * v6_dma_clean_range(start,end) | ||
176 | * - start - virtual start address of region | ||
177 | * - end - virtual end address of region | ||
178 | */ | ||
179 | ENTRY(v6_dma_clean_range) | ||
180 | bic r0, r0, #D_CACHE_LINE_SIZE - 1 | ||
181 | 1: | ||
182 | #ifdef HARVARD_CACHE | ||
183 | mcr p15, 0, r0, c7, c10, 1 @ clean D line | ||
184 | #else | ||
185 | mcr p15, 0, r0, c7, c11, 1 @ clean unified line | ||
186 | #endif | ||
187 | add r0, r0, #D_CACHE_LINE_SIZE | ||
188 | cmp r0, r1 | ||
189 | blo 1b | ||
190 | mov r0, #0 | ||
191 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
192 | mov pc, lr | ||
193 | |||
194 | /* | ||
195 | * v6_dma_flush_range(start,end) | ||
196 | * - start - virtual start address of region | ||
197 | * - end - virtual end address of region | ||
198 | */ | ||
199 | ENTRY(v6_dma_flush_range) | ||
200 | bic r0, r0, #D_CACHE_LINE_SIZE - 1 | ||
201 | 1: | ||
202 | #ifdef HARVARD_CACHE | ||
203 | mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line | ||
204 | #else | ||
205 | mcr p15, 0, r0, c7, c15, 1 @ clean & invalidate line | ||
206 | #endif | ||
207 | add r0, r0, #D_CACHE_LINE_SIZE | ||
208 | cmp r0, r1 | ||
209 | blo 1b | ||
210 | mov r0, #0 | ||
211 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
212 | mov pc, lr | ||
213 | |||
214 | __INITDATA | ||
215 | |||
216 | .type v6_cache_fns, #object | ||
217 | ENTRY(v6_cache_fns) | ||
218 | .long v6_flush_kern_cache_all | ||
219 | .long v6_flush_user_cache_all | ||
220 | .long v6_flush_user_cache_range | ||
221 | .long v6_coherent_kern_range | ||
222 | .long v6_coherent_user_range | ||
223 | .long v6_flush_kern_dcache_page | ||
224 | .long v6_dma_inv_range | ||
225 | .long v6_dma_clean_range | ||
226 | .long v6_dma_flush_range | ||
227 | .size v6_cache_fns, . - v6_cache_fns | ||