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(){ 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(){ 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() 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() 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(){ 156 dcache_maint(1); 157 } 158 static inline void dcache_invalidate (){ 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() 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() 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() 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() 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() 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() 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() 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() 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() 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() 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() 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() 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() 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