This source file includes following definitions.
- icache_flush_all
- log_2_n_round_up
- get_clidr
- get_ccsidr
- set_csselr
- v7_inval_dcache_level_setway
- v7_clean_inval_dcache_level_setway
- v7_maint_dcache_level_setway
- v7_maint_dcache_all
- dcache_clean_all
- cache_get_config
- dcache_get_size
- icache_flush_all
- dcache_clean_all
1
2
3
4
5
6 #ifdef THUMB_FW
7
8
9
10 void __attribute__((naked,noinline)) icache_flush_all(void)
11 {
12
13
14
15
16 asm volatile (
17 "mov r1, #0\n"
18 "mcr p15, 0, r1, c7, c5, 0\n"
19 "mcr p15, 0, r1, c7, c5, 6\n"
20 "dsb sy\n"
21 "isb sy\n"
22 "bx lr\n"
23 );
24 }
25
26
27 #define ARMV7_CLIDR_CTYPE_NO_CACHE 0
28 #define ARMV7_CLIDR_CTYPE_INSTRUCTION_ONLY 1
29 #define ARMV7_CLIDR_CTYPE_DATA_ONLY 2
30 #define ARMV7_CLIDR_CTYPE_INSTRUCTION_DATA 3
31 #define ARMV7_CLIDR_CTYPE_UNIFIED 4
32
33 #define ARMV7_DCACHE_INVAL_ALL 1
34 #define ARMV7_DCACHE_CLEAN_INVAL_ALL 2
35 #define ARMV7_DCACHE_INVAL_RANGE 3
36 #define ARMV7_DCACHE_CLEAN_INVAL_RANGE 4
37
38 #define ARMV7_CSSELR_IND_DATA_UNIFIED 0
39 #define ARMV7_CSSELR_IND_INSTRUCTION 1
40
41 #define CCSIDR_LINE_SIZE_OFFSET 0
42 #define CCSIDR_LINE_SIZE_MASK 0x7
43 #define CCSIDR_ASSOCIATIVITY_OFFSET 3
44 #define CCSIDR_ASSOCIATIVITY_MASK (0x3FF << 3)
45 #define CCSIDR_NUM_SETS_OFFSET 13
46 #define CCSIDR_NUM_SETS_MASK (0x7FFF << 13)
47
48 typedef unsigned int u32;
49 typedef int s32;
50
51 static inline s32 log_2_n_round_up(u32 n)
52 {
53 s32 log2n = -1;
54 u32 temp = n;
55
56 while (temp) {
57 log2n++;
58 temp >>= 1;
59 }
60
61 if (n & (n - 1))
62 return log2n + 1;
63 else
64 return log2n;
65 }
66
67 static u32 get_clidr(void)
68 {
69 u32 clidr;
70
71
72 asm volatile ("mrc p15,1,%0,c0,c0,1" : "=r" (clidr));
73 return clidr;
74 }
75
76 static u32 get_ccsidr(void)
77 {
78 u32 ccsidr;
79
80
81 asm volatile ("mrc p15, 1, %0, c0, c0, 0" : "=r" (ccsidr));
82 return ccsidr;
83 }
84
85 static void set_csselr(u32 level, u32 type)
86 { u32 csselr = level << 1 | type;
87
88
89 asm volatile ("mcr p15, 2, %0, c0, c0, 0" : : "r" (csselr));
90 }
91
92 static void v7_inval_dcache_level_setway(u32 level, u32 num_sets,
93 u32 num_ways, u32 way_shift,
94 u32 log2_line_len)
95 {
96 int way, set, setway;
97
98
99
100
101
102
103 for (way = num_ways - 1; way >= 0 ; way--) {
104 for (set = num_sets - 1; set >= 0; set--) {
105 setway = (level << 1) | (set << log2_line_len) |
106 (way << way_shift);
107
108 asm volatile (" mcr p15, 0, %0, c7, c6, 2"
109 : : "r" (setway));
110 }
111 }
112
113 asm volatile("dsb sy\n");
114 }
115
116 static void v7_clean_inval_dcache_level_setway(u32 level, u32 num_sets,
117 u32 num_ways, u32 way_shift,
118 u32 log2_line_len)
119 {
120 int way, set, setway;
121
122
123
124
125
126
127 for (way = num_ways - 1; way >= 0 ; way--) {
128 for (set = num_sets - 1; set >= 0; set--) {
129 setway = (level << 1) | (set << log2_line_len) |
130 (way << way_shift);
131
132
133
134
135 asm volatile (" mcr p15, 0, %0, c7, c14, 2"
136 : : "r" (setway));
137 }
138 }
139
140 asm volatile("dsb sy\n");
141 }
142
143 static void v7_maint_dcache_level_setway(u32 level, u32 operation)
144 {
145 u32 ccsidr;
146 u32 num_sets, num_ways, log2_line_len, log2_num_ways;
147 u32 way_shift;
148
149 set_csselr(level, ARMV7_CSSELR_IND_DATA_UNIFIED);
150
151 ccsidr = get_ccsidr();
152
153 log2_line_len = ((ccsidr & CCSIDR_LINE_SIZE_MASK) >>
154 CCSIDR_LINE_SIZE_OFFSET) + 2;
155
156 log2_line_len += 2;
157
158 num_ways = ((ccsidr & CCSIDR_ASSOCIATIVITY_MASK) >>
159 CCSIDR_ASSOCIATIVITY_OFFSET) + 1;
160 num_sets = ((ccsidr & CCSIDR_NUM_SETS_MASK) >>
161 CCSIDR_NUM_SETS_OFFSET) + 1;
162
163
164
165
166 log2_num_ways = log_2_n_round_up(num_ways);
167
168 way_shift = (32 - log2_num_ways);
169 if (operation == ARMV7_DCACHE_INVAL_ALL) {
170 v7_inval_dcache_level_setway(level, num_sets, num_ways,
171 way_shift, log2_line_len);
172 } else if (operation == ARMV7_DCACHE_CLEAN_INVAL_ALL) {
173 v7_clean_inval_dcache_level_setway(level, num_sets, num_ways,
174 way_shift, log2_line_len);
175 }
176 }
177
178 static void v7_maint_dcache_all(u32 operation)
179 {
180 u32 level, cache_type, level_start_bit = 0;
181
182 u32 clidr = get_clidr();
183
184 for (level = 0; level < 7; level++) {
185 cache_type = (clidr >> level_start_bit) & 0x7;
186 if ((cache_type == ARMV7_CLIDR_CTYPE_DATA_ONLY) ||
187 (cache_type == ARMV7_CLIDR_CTYPE_INSTRUCTION_DATA) ||
188 (cache_type == ARMV7_CLIDR_CTYPE_UNIFIED))
189 v7_maint_dcache_level_setway(level, operation);
190 level_start_bit += 3;
191 }
192 }
193
194 void dcache_clean_all(void) {
195 v7_maint_dcache_all(ARMV7_DCACHE_CLEAN_INVAL_ALL);
196
197 }
198
199 #else
200
201
202
203
204 void __attribute__((naked,noinline)) cache_get_config(void) {
205 asm volatile (
206 "MRC p15, 0, R0,c0,c0,1\n"
207 "BX LR\n"
208 );
209 }
210
211
212
213
214 unsigned dcache_get_size(unsigned config) {
215 unsigned sz = (config>>18) & 0xF;
216
217 if(sz == 0) {
218 return 0;
219 }
220
221
222 return 0x200 << sz;
223 }
224
225
226
227
228 void __attribute__((naked,noinline)) icache_flush_all(void) {
229 asm volatile (
230 "MOV r1, #0\n"
231 "MCR p15, 0, r1,c7,c5\n"
232 "BX LR\n"
233 );
234 }
235
236
237
238
239
240
241 void __attribute__((naked,noinline)) dcache_clean_all(void) {
242 asm volatile (
243 "PUSH {LR}\n"
244 "BL cache_get_config\n"
245 "BL dcache_get_size\n"
246 "CMP r0, #0\n"
247 "BEQ 3f\n"
248
249
250 "LSR r3, r0, #2\n"
251 "MOV r1, #0\n"
252 "2:\n"
253 "MOV r0, #0\n"
254 "1:\n"
255 "ORR r2,r1,r0\n"
256 "MCR p15, 0, r2, c7, c10, 2\n"
257 "ADD r0, r0, #0x20\n"
258 "CMP r0, r3\n"
259 "BNE 1b\n"
260 "ADD r1, r1,#0x40000000\n"
261 "CMP r1, #0\n"
262 "BNE 2b\n"
263 "MCR p15, 0, r1, c7, c10, 4\n"
264 "3:\n"
265 "POP {LR}\n"
266 "BX LR\n"
267 );
268 }