xref: /minix/minix/kernel/arch/earm/include/cpufunc.h (revision fb4fbf7a)
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 */
22 static inline void dmb(void)
23 {
24 	asm volatile("dmb" : : : "memory");
25 }
26 
27 /* Data synchronization barrier */
28 static inline void dsb(void)
29 {
30 	asm volatile("dsb" : : : "memory");
31 }
32 
33 /* Instruction synchronization barrier */
34 static inline void isb(void)
35 {
36 	asm volatile("isb" : : : "memory");
37 }
38 
39 static inline void barrier(void)
40 {
41 	dsb();
42 	isb();
43 }
44 
45 
46 /* Read CLIDR, Cache Level ID Register */
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 */
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 */
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 */
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 */
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 */
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 */
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  */
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 }
155 static inline void dcache_clean(void){
156 	dcache_maint(1);
157 }
158 static inline void dcache_invalidate(void){
159 	dcache_maint(2);
160 }
161 
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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  */
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 */
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 */
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 */
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 */
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