1 #ifndef _ARM_CPUFUNC_H
2 #define _ARM_CPUFUNC_H
3
4 #if 0
5 /* check interrupt state */
6 static inline void check_int(unsigned int state, int line)
7 {
8 unsigned int cpsr = 0;
9
10 asm volatile("mrs %0, cpsr" : "=r" (cpsr));
11
12 if ((cpsr & PSR_F) != (state & PSR_F))
13 printf("%d: FIQs are unexpectedly %s\n", line, (cpsr & PSR_F) ? "MASKED" : "UNMASKED");
14
15 if ((cpsr & PSR_I) != (state & PSR_I))
16 printf("%d: IRQs are unexpectedly %s\n", line, (cpsr & PSR_I) ? "MASKED" : "UNMASKED");
17
18 }
19 #endif
20
21 /* Data memory barrier */
dmb(void)22 static inline void dmb(void)
23 {
24 asm volatile("dmb" : : : "memory");
25 }
26
27 /* Data synchronization barrier */
dsb(void)28 static inline void dsb(void)
29 {
30 asm volatile("dsb" : : : "memory");
31 }
32
33 /* Instruction synchronization barrier */
isb(void)34 static inline void isb(void)
35 {
36 asm volatile("isb" : : : "memory");
37 }
38
barrier(void)39 static inline void barrier(void)
40 {
41 dsb();
42 isb();
43 }
44
45
46 /* Read CLIDR, Cache Level ID Register */
read_clidr(void)47 static inline u32_t read_clidr(void){
48 u32_t clidr;
49 asm volatile("mrc p15, 1, %[clidr], c0, c0 , 1 @ READ CLIDR\n\t"
50 : [clidr] "=r" (clidr));
51 return clidr;
52 }
53
54
55 /* Read CSSELR, Cache Size Selection Register */
read_csselr(void)56 static inline u32_t read_csselr(void){
57 u32_t csselr;
58 asm volatile("mrc p15, 2, %[csselr], c0, c0 , 0 @ READ CSSELR\n\t"
59 : [csselr] "=r" (csselr));
60 return csselr;
61 }
62
63 /* Write CSSELR, Cache Size Selection Register */
write_csselr(u32_t csselr)64 static inline void write_csselr(u32_t csselr){
65 asm volatile("mcr p15, 2, %[csselr], c0, c0 , 0 @ WRITE CSSELR\n\t"
66 : : [csselr] "r" (csselr));
67 }
68
69 /* Read Cache Size ID Register */
read_ccsidr(void)70 static inline u32_t read_ccsidr(void)
71 {
72 u32_t ccsidr;
73 asm volatile("mrc p15, 1, %[ccsidr], c0, c0, 0 @ Read CCSIDR\n\t"
74 : [ccsidr] "=r" (ccsidr));
75 return ccsidr;
76 }
77
78 /* Read TLBTR, TLB Type Register */
read_tlbtr(void)79 static inline u32_t read_tlbtr(void)
80 {
81 u32_t tlbtr;
82 asm volatile("mrc p15, 0, %[tlbtr], c0, c0, 3 @ Read TLBTR\n\t"
83 : [tlbtr] "=r" (tlbtr));
84 return tlbtr;
85 }
86
87 /* keesj:move these out */
ilog2(u32_t t)88 static inline u32_t ilog2(u32_t t)
89 {
90 u32_t counter =0;
91 while( (t = t >> 1) ) counter ++;
92 return counter;
93 }
94
95 /* keesj:move these out */
ipow2(u32_t t)96 static inline u32_t ipow2(u32_t t)
97 {
98 return 1 << t;
99 }
100
101 /*
102 * type = 1 == CLEAN
103 * type = 2 == INVALIDATE
104 */
dcache_maint(int type)105 static inline void dcache_maint(int type){
106 u32_t cache_level ;
107 u32_t clidr;
108 u32_t ctype;
109 u32_t ccsidr;
110 u32_t line_size,line_length;
111 u32_t number_of_sets,number_of_ways;
112 u32_t set,way;
113
114 clidr = read_clidr();
115 u32_t loc = ( clidr >> 24) & 0x7;
116 u32_t louu = ( clidr >> 27) & 0x7;
117 u32_t louis = ( clidr >> 21) & 0x7;
118 for (cache_level =0 ; cache_level < loc; cache_level++){
119 /* get current cache type */
120 ctype = ( clidr >> cache_level*3) & 0x7;
121 /* select data or unified or cache level */
122 write_csselr(cache_level << 1);
123 isb();
124 ccsidr = read_ccsidr();
125 line_size = ccsidr & 0x7;
126 line_length = 2 << (line_size + 1) ; /* 2**(line_size + 2) */
127 number_of_sets = ((ccsidr >> 13) & 0x7fff) + 1;
128 number_of_ways = ((ccsidr >> 3) & 0x3ff) + 1;
129
130 u32_t way_bits = ilog2(number_of_ways);
131 if(ipow2(ilog2(number_of_ways) < number_of_ways) ) {
132 way_bits++;
133 }
134
135 u32_t l = ilog2(line_length);
136 for (way =0 ; way < number_of_ways; way++) {
137 for (set =0 ; set < number_of_sets; set++) {
138 u32_t val = ( way << (32 - way_bits) ) | (set << l) | (cache_level << 1 );
139 if (type == 1) {
140 /* DCCISW, Data Cache Clean and Invalidate by Set/Way */
141 asm volatile("mcr p15, 0, %[set], c7, c14, 2 @ DCCISW"
142 : : [set] "r" (val));
143 } else if (type ==2 ){
144 /* DCISW, Data Cache Invalidate by Set/Way */
145 asm volatile("mcr p15, 0, %[set], c7, c6, 2"
146 : : [set] "r" (val));
147 }
148 }
149 }
150 }
151 dsb();
152 isb();
153
154 }
dcache_clean(void)155 static inline void dcache_clean(void){
156 dcache_maint(1);
157 }
dcache_invalidate(void)158 static inline void dcache_invalidate(void){
159 dcache_maint(2);
160 }
161
refresh_tlb(void)162 static inline void refresh_tlb(void)
163 {
164 dsb();
165
166 /* Invalidate entire unified TLB */
167 asm volatile("mcr p15, 0, %[zero], c8, c7, 0 @ TLBIALL\n\t" : : [zero] "r" (0));
168
169 #if 0
170 /* Invalidate entire data TLB */
171 asm volatile("mcr p15, 0, %[zero], c8, c6, 0" : : [zero] "r" (0));
172
173 /* Invalidate entire instruction TLB */
174 asm volatile("mcr p15, 0, %[zero], c8, c5, 0" : : [zero] "r" (0));
175 #endif
176
177 /*
178 * Invalidate all instruction caches to PoU.
179 * Also flushes branch target cache.
180 */
181 asm volatile("mcr p15, 0, %[zero], c7, c5, 0" : : [zero] "r" (0));
182
183 /* Invalidate entire branch predictor array */
184 asm volatile("mcr p15, 0, %[zero], c7, c5, 6" : : [zero] "r" (0)); /* flush BTB */
185
186 dsb();
187 isb();
188 }
189
190
191 /* Read System Control Register */
read_sctlr(void)192 static inline u32_t read_sctlr(void)
193 {
194 u32_t ctl;
195
196 asm volatile("mrc p15, 0, %[ctl], c1, c0, 0 @ Read SCTLR\n\t"
197 : [ctl] "=r" (ctl));
198
199 return ctl;
200 }
201
202 /* Write System Control Register */
write_sctlr(u32_t ctl)203 static inline void write_sctlr(u32_t ctl)
204 {
205 asm volatile("mcr p15, 0, %[ctl], c1, c0, 0 @ Write SCTLR\n\t"
206 : : [ctl] "r" (ctl));
207 isb();
208 }
209
210 /* Read Translation Table Base Register 0 */
read_ttbr0(void)211 static inline u32_t read_ttbr0(void)
212 {
213 u32_t bar;
214
215 asm volatile("mrc p15, 0, %[bar], c2, c0, 0 @ Read TTBR0\n\t"
216 : [bar] "=r" (bar));
217
218 return bar & ARM_TTBR_ADDR_MASK;
219 }
220
221 /* Write Translation Table Base Register 0 */
write_ttbr0(u32_t bar)222 static inline void write_ttbr0(u32_t bar)
223 {
224 barrier();
225 /* In our setup TTBR contains the base address *and* the flags
226 but other pieces of the kernel code expect ttbr to be the
227 base address of the l1 page table. We therefore add the
228 flags here and remove them in the read_ttbr0 */
229 u32_t v = (bar & ARM_TTBR_ADDR_MASK ) | ARM_TTBR_FLAGS_CACHED;
230 asm volatile("mcr p15, 0, %[bar], c2, c0, 0 @ Write TTBR0\n\t"
231 : : [bar] "r" (v));
232
233 refresh_tlb();
234 }
235
236 /* Reload Translation Table Base Register 0 */
reload_ttbr0(void)237 static inline void reload_ttbr0(void)
238 {
239 reg_t ttbr = read_ttbr0();
240 write_ttbr0(ttbr);
241 }
242
243 /* Read Translation Table Base Register 1 */
read_ttbr1(void)244 static inline u32_t read_ttbr1(void)
245 {
246 u32_t bar;
247
248 asm volatile("mrc p15, 0, %[bar], c2, c0, 1 @ Read TTBR1\n\t"
249 : [bar] "=r" (bar));
250
251 return bar;
252 }
253
254 /* Write Translation Table Base Register 1 */
write_ttbr1(u32_t bar)255 static inline void write_ttbr1(u32_t bar)
256 {
257 barrier();
258
259 asm volatile("mcr p15, 0, %[bar], c2, c0, 1 @ Write TTBR1\n\t"
260 : : [bar] "r" (bar));
261
262 refresh_tlb();
263 }
264
265 /* Reload Translation Table Base Register 1 */
reload_ttbr1(void)266 static inline void reload_ttbr1(void)
267 {
268 reg_t ttbr = read_ttbr1();
269
270 write_ttbr1(ttbr);
271 }
272
273 /* Read Translation Table Base Control Register */
read_ttbcr(void)274 static inline u32_t read_ttbcr(void)
275 {
276 u32_t bcr;
277
278 asm volatile("mrc p15, 0, %[bcr], c2, c0, 2 @ Read TTBCR\n\t"
279 : [bcr] "=r" (bcr));
280
281 return bcr;
282 }
283
284 /* Write Translation Table Base Control Register */
write_ttbcr(u32_t bcr)285 static inline void write_ttbcr(u32_t bcr)
286 {
287 asm volatile("mcr p15, 0, %[bcr], c2, c0, 2 @ Write TTBCR\n\t"
288 : : [bcr] "r" (bcr));
289
290 isb();
291 }
292
293 /* Read Domain Access Control Register */
read_dacr(void)294 static inline u32_t read_dacr(void)
295 {
296 u32_t dacr;
297
298 asm volatile("mrc p15, 0, %[dacr], c3, c0, 0 @ Read DACR\n\t"
299 : [dacr] "=r" (dacr));
300
301 return dacr;
302 }
303
304 /* Write Domain Access Control Register */
write_dacr(u32_t dacr)305 static inline void write_dacr(u32_t dacr)
306 {
307 asm volatile("mcr p15, 0, %[dacr], c3, c0, 0 @ Write DACR\n\t"
308 : : [dacr] "r" (dacr));
309
310 isb();
311 }
312
313 /* Read Data Fault Status Register */
read_dfsr(void)314 static inline u32_t read_dfsr(void)
315 {
316 u32_t fsr;
317
318 asm volatile("mrc p15, 0, %[fsr], c5, c0, 0 @ Read DFSR\n\t"
319 : [fsr] "=r" (fsr));
320
321 return fsr;
322 }
323
324 /* Write Data Fault Status Register */
write_dfsr(u32_t fsr)325 static inline void write_dfsr(u32_t fsr)
326 {
327 asm volatile("mcr p15, 0, %[fsr], c5, c0, 0 @ Write DFSR\n\t"
328 : : [fsr] "r" (fsr));
329
330 isb();
331 }
332
333 /* Read Instruction Fault Status Register */
read_ifsr(void)334 static inline u32_t read_ifsr(void)
335 {
336 u32_t fsr;
337
338 asm volatile("mrc p15, 0, %[fsr], c5, c0, 1 @ Read IFSR\n\t"
339 : [fsr] "=r" (fsr));
340
341 return fsr;
342 }
343
344 /* Write Instruction Fault Status Register */
write_ifsr(u32_t fsr)345 static inline void write_ifsr(u32_t fsr)
346 {
347 asm volatile("mcr p15, 0, %[fsr], c5, c0, 1 @ Write IFSR\n\t"
348 : : [fsr] "r" (fsr));
349
350 isb();
351 }
352
353 /* Read Data Fault Address Register */
read_dfar(void)354 static inline u32_t read_dfar(void)
355 {
356 u32_t far;
357
358 asm volatile("mrc p15, 0, %[far], c6, c0, 0 @ Read DFAR\n\t"
359 : [far] "=r" (far));
360
361 return far;
362 }
363
364 /* Write Data Fault Address Register */
write_dfar(u32_t far)365 static inline void write_dfar(u32_t far)
366 {
367 asm volatile("mcr p15, 0, %[far], c6, c0, 0 @ Write DFAR\n\t"
368 : : [far] "r" (far));
369
370 isb();
371 }
372
373 /* Read Instruction Fault Address Register */
read_ifar(void)374 static inline u32_t read_ifar(void)
375 {
376 u32_t far;
377
378 asm volatile("mrc p15, 0, %[far], c6, c0, 2 @ Read IFAR\n\t"
379 : [far] "=r" (far));
380
381 return far;
382 }
383
384 /* Write Instruction Fault Address Register */
write_ifar(u32_t far)385 static inline void write_ifar(u32_t far)
386 {
387 asm volatile("mcr p15, 0, %[far], c6, c0, 2 @ Write IFAR\n\t"
388 : : [far] "r" (far));
389
390 isb();
391 }
392
393 /* Read Vector Base Address Register */
read_vbar(void)394 static inline u32_t read_vbar(void)
395 {
396 u32_t vbar;
397
398 asm volatile("mrc p15, 0, %[vbar], c12, c0, 0 @ Read VBAR\n\t"
399 : [vbar] "=r" (vbar));
400
401 return vbar;
402 }
403
404 /* Write Vector Base Address Register */
write_vbar(u32_t vbar)405 static inline void write_vbar(u32_t vbar)
406 {
407 asm volatile("mcr p15, 0, %[vbar], c12, c0, 0 @ Write VBAR\n\t"
408 : : [vbar] "r" (vbar));
409
410 isb();
411 }
412
413 /* Read the Main ID Register */
read_midr(void)414 static inline u32_t read_midr(void)
415 {
416 u32_t id;
417
418 asm volatile("mrc p15, 0, %[id], c0, c0, 0 @ read MIDR\n\t"
419 : [id] "=r" (id));
420
421 return id;
422 }
423
424 /* Read Auxiliary Control Register */
read_actlr(void)425 static inline u32_t read_actlr(void)
426 {
427 u32_t ctl;
428
429 asm volatile("mrc p15, 0, %[ctl], c1, c0, 1 @ Read ACTLR\n\t"
430 : [ctl] "=r" (ctl));
431
432 return ctl;
433 }
434
435 /* Write Auxiliary Control Register */
write_actlr(u32_t ctl)436 static inline void write_actlr(u32_t ctl)
437 {
438 //http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344k/Babjbjbb.html
439 asm volatile("mcr p15, 0, %[ctl], c1, c0, 1 @ Write ACTLR\n\t"
440 : : [ctl] "r" (ctl));
441
442 isb();
443 }
444
445 /* Read Current Program Status Register */
read_cpsr(void)446 static inline u32_t read_cpsr(void)
447 {
448 u32_t status;
449
450 asm volatile("mrs %[status], cpsr @ read CPSR"
451 : [status] "=r" (status));
452
453 return status;
454 }
455
456 /* Write Current Program Status Register */
write_cpsr(u32_t status)457 static inline void write_cpsr(u32_t status)
458 {
459 asm volatile("msr cpsr_c, %[status] @ write CPSR"
460 : : [status] "r" (status));
461 }
462
463 #endif /* _ARM_CPUFUNC_H */
464