1/* 2 * linux/arch/arm/mm/proc-arm1026.S: MMU functions for ARM1026EJ-S 3 * 4 * Copyright (C) 2000 ARM Limited 5 * Copyright (C) 2000 Deep Blue Solutions Ltd. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * 13 * These are the low level assembler for performing cache and TLB 14 * functions on the ARM1026EJ-S. 15 */ 16#include <linux/linkage.h> 17#include <linux/config.h> 18#include <linux/init.h> 19#include <asm/assembler.h> 20#include <asm/asm-offsets.h> 21#include <asm/pgtable-hwdef.h> 22#include <asm/pgtable.h> 23#include <asm/procinfo.h> 24#include <asm/ptrace.h> 25 26/* 27 * This is the maximum size of an area which will be invalidated 28 * using the single invalidate entry instructions. Anything larger 29 * than this, and we go for the whole cache. 30 * 31 * This value should be chosen such that we choose the cheapest 32 * alternative. 33 */ 34#define MAX_AREA_SIZE 32768 35 36/* 37 * The size of one data cache line. 38 */ 39#define CACHE_DLINESIZE 32 40 41/* 42 * The number of data cache segments. 43 */ 44#define CACHE_DSEGMENTS 16 45 46/* 47 * The number of lines in a cache segment. 48 */ 49#define CACHE_DENTRIES 64 50 51/* 52 * This is the size at which it becomes more efficient to 53 * clean the whole cache, rather than using the individual 54 * cache line maintainence instructions. 55 */ 56#define CACHE_DLIMIT 32768 57 58 .text 59/* 60 * cpu_arm1026_proc_init() 61 */ 62ENTRY(cpu_arm1026_proc_init) 63 mov pc, lr 64 65/* 66 * cpu_arm1026_proc_fin() 67 */ 68ENTRY(cpu_arm1026_proc_fin) 69 stmfd sp!, {lr} 70 mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE 71 msr cpsr_c, ip 72 bl arm1026_flush_kern_cache_all 73 mrc p15, 0, r0, c1, c0, 0 @ ctrl register 74 bic r0, r0, #0x1000 @ ...i............ 75 bic r0, r0, #0x000e @ ............wca. 76 mcr p15, 0, r0, c1, c0, 0 @ disable caches 77 ldmfd sp!, {pc} 78 79/* 80 * cpu_arm1026_reset(loc) 81 * 82 * Perform a soft reset of the system. Put the CPU into the 83 * same state as it would be if it had been reset, and branch 84 * to what would be the reset vector. 85 * 86 * loc: location to jump to for soft reset 87 */ 88 .align 5 89ENTRY(cpu_arm1026_reset) 90 mov ip, #0 91 mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches 92 mcr p15, 0, ip, c7, c10, 4 @ drain WB 93 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs 94 mrc p15, 0, ip, c1, c0, 0 @ ctrl register 95 bic ip, ip, #0x000f @ ............wcam 96 bic ip, ip, #0x1100 @ ...i...s........ 97 mcr p15, 0, ip, c1, c0, 0 @ ctrl register 98 mov pc, r0 99 100/* 101 * cpu_arm1026_do_idle() 102 */ 103 .align 5 104ENTRY(cpu_arm1026_do_idle) 105 mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt 106 mov pc, lr 107 108/* ================================= CACHE ================================ */ 109 110 .align 5 111/* 112 * flush_user_cache_all() 113 * 114 * Invalidate all cache entries in a particular address 115 * space. 116 */ 117ENTRY(arm1026_flush_user_cache_all) 118 /* FALLTHROUGH */ 119/* 120 * flush_kern_cache_all() 121 * 122 * Clean and invalidate the entire cache. 123 */ 124ENTRY(arm1026_flush_kern_cache_all) 125 mov r2, #VM_EXEC 126 mov ip, #0 127__flush_whole_cache: 128#ifndef CONFIG_CPU_DCACHE_DISABLE 1291: mrc p15, 0, r15, c7, c14, 3 @ test, clean, invalidate 130 bne 1b 131#endif 132 tst r2, #VM_EXEC 133#ifndef CONFIG_CPU_ICACHE_DISABLE 134 mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache 135#endif 136 mcrne p15, 0, ip, c7, c10, 4 @ drain WB 137 mov pc, lr 138 139/* 140 * flush_user_cache_range(start, end, flags) 141 * 142 * Invalidate a range of cache entries in the specified 143 * address space. 144 * 145 * - start - start address (inclusive) 146 * - end - end address (exclusive) 147 * - flags - vm_flags for this space 148 */ 149ENTRY(arm1026_flush_user_cache_range) 150 mov ip, #0 151 sub r3, r1, r0 @ calculate total size 152 cmp r3, #CACHE_DLIMIT 153 bhs __flush_whole_cache 154 155#ifndef CONFIG_CPU_DCACHE_DISABLE 1561: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry 157 add r0, r0, #CACHE_DLINESIZE 158 cmp r0, r1 159 blo 1b 160#endif 161 tst r2, #VM_EXEC 162#ifndef CONFIG_CPU_ICACHE_DISABLE 163 mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache 164#endif 165 mcrne p15, 0, ip, c7, c10, 4 @ drain WB 166 mov pc, lr 167 168/* 169 * coherent_kern_range(start, end) 170 * 171 * Ensure coherency between the Icache and the Dcache in the 172 * region described by start. If you have non-snooping 173 * Harvard caches, you need to implement this function. 174 * 175 * - start - virtual start address 176 * - end - virtual end address 177 */ 178ENTRY(arm1026_coherent_kern_range) 179 /* FALLTHROUGH */ 180/* 181 * coherent_user_range(start, end) 182 * 183 * Ensure coherency between the Icache and the Dcache in the 184 * region described by start. If you have non-snooping 185 * Harvard caches, you need to implement this function. 186 * 187 * - start - virtual start address 188 * - end - virtual end address 189 */ 190ENTRY(arm1026_coherent_user_range) 191 mov ip, #0 192 bic r0, r0, #CACHE_DLINESIZE - 1 1931: 194#ifndef CONFIG_CPU_DCACHE_DISABLE 195 mcr p15, 0, r0, c7, c10, 1 @ clean D entry 196#endif 197#ifndef CONFIG_CPU_ICACHE_DISABLE 198 mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry 199#endif 200 add r0, r0, #CACHE_DLINESIZE 201 cmp r0, r1 202 blo 1b 203 mcr p15, 0, ip, c7, c10, 4 @ drain WB 204 mov pc, lr 205 206/* 207 * flush_kern_dcache_page(void *page) 208 * 209 * Ensure no D cache aliasing occurs, either with itself or 210 * the I cache 211 * 212 * - page - page aligned address 213 */ 214ENTRY(arm1026_flush_kern_dcache_page) 215 mov ip, #0 216#ifndef CONFIG_CPU_DCACHE_DISABLE 217 add r1, r0, #PAGE_SZ 2181: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry 219 add r0, r0, #CACHE_DLINESIZE 220 cmp r0, r1 221 blo 1b 222#endif 223 mcr p15, 0, ip, c7, c10, 4 @ drain WB 224 mov pc, lr 225 226/* 227 * dma_inv_range(start, end) 228 * 229 * Invalidate (discard) the specified virtual address range. 230 * May not write back any entries. If 'start' or 'end' 231 * are not cache line aligned, those lines must be written 232 * back. 233 * 234 * - start - virtual start address 235 * - end - virtual end address 236 * 237 * (same as v4wb) 238 */ 239ENTRY(arm1026_dma_inv_range) 240 mov ip, #0 241#ifndef CONFIG_CPU_DCACHE_DISABLE 242 tst r0, #CACHE_DLINESIZE - 1 243 bic r0, r0, #CACHE_DLINESIZE - 1 244 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry 245 tst r1, #CACHE_DLINESIZE - 1 246 mcrne p15, 0, r1, c7, c10, 1 @ clean D entry 2471: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 248 add r0, r0, #CACHE_DLINESIZE 249 cmp r0, r1 250 blo 1b 251#endif 252 mcr p15, 0, ip, c7, c10, 4 @ drain WB 253 mov pc, lr 254 255/* 256 * dma_clean_range(start, end) 257 * 258 * Clean the specified virtual address range. 259 * 260 * - start - virtual start address 261 * - end - virtual end address 262 * 263 * (same as v4wb) 264 */ 265ENTRY(arm1026_dma_clean_range) 266 mov ip, #0 267#ifndef CONFIG_CPU_DCACHE_DISABLE 268 bic r0, r0, #CACHE_DLINESIZE - 1 2691: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 270 add r0, r0, #CACHE_DLINESIZE 271 cmp r0, r1 272 blo 1b 273#endif 274 mcr p15, 0, ip, c7, c10, 4 @ drain WB 275 mov pc, lr 276 277/* 278 * dma_flush_range(start, end) 279 * 280 * Clean and invalidate the specified virtual address range. 281 * 282 * - start - virtual start address 283 * - end - virtual end address 284 */ 285ENTRY(arm1026_dma_flush_range) 286 mov ip, #0 287#ifndef CONFIG_CPU_DCACHE_DISABLE 288 bic r0, r0, #CACHE_DLINESIZE - 1 2891: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry 290 add r0, r0, #CACHE_DLINESIZE 291 cmp r0, r1 292 blo 1b 293#endif 294 mcr p15, 0, ip, c7, c10, 4 @ drain WB 295 mov pc, lr 296 297ENTRY(arm1026_cache_fns) 298 .long arm1026_flush_kern_cache_all 299 .long arm1026_flush_user_cache_all 300 .long arm1026_flush_user_cache_range 301 .long arm1026_coherent_kern_range 302 .long arm1026_coherent_user_range 303 .long arm1026_flush_kern_dcache_page 304 .long arm1026_dma_inv_range 305 .long arm1026_dma_clean_range 306 .long arm1026_dma_flush_range 307 308 .align 5 309ENTRY(cpu_arm1026_dcache_clean_area) 310#ifndef CONFIG_CPU_DCACHE_DISABLE 311 mov ip, #0 3121: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 313 add r0, r0, #CACHE_DLINESIZE 314 subs r1, r1, #CACHE_DLINESIZE 315 bhi 1b 316#endif 317 mov pc, lr 318 319/* =============================== PageTable ============================== */ 320 321/* 322 * cpu_arm1026_switch_mm(pgd) 323 * 324 * Set the translation base pointer to be as described by pgd. 325 * 326 * pgd: new page tables 327 */ 328 .align 5 329ENTRY(cpu_arm1026_switch_mm) 330 mov r1, #0 331#ifndef CONFIG_CPU_DCACHE_DISABLE 3321: mrc p15, 0, r15, c7, c14, 3 @ test, clean, invalidate 333 bne 1b 334#endif 335#ifndef CONFIG_CPU_ICACHE_DISABLE 336 mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache 337#endif 338 mcr p15, 0, r1, c7, c10, 4 @ drain WB 339 mcr p15, 0, r0, c2, c0, 0 @ load page table pointer 340 mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs 341 mov pc, lr 342 343/* 344 * cpu_arm1026_set_pte(ptep, pte) 345 * 346 * Set a PTE and flush it out 347 */ 348 .align 5 349ENTRY(cpu_arm1026_set_pte) 350 str r1, [r0], #-2048 @ linux version 351 352 eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY 353 354 bic r2, r1, #PTE_SMALL_AP_MASK 355 bic r2, r2, #PTE_TYPE_MASK 356 orr r2, r2, #PTE_TYPE_SMALL 357 358 tst r1, #L_PTE_USER @ User? 359 orrne r2, r2, #PTE_SMALL_AP_URO_SRW 360 361 tst r1, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty? 362 orreq r2, r2, #PTE_SMALL_AP_UNO_SRW 363 364 tst r1, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young? 365 movne r2, #0 366 367#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 368 eor r3, r1, #0x0a @ C & small page? 369 tst r3, #0x0b 370 biceq r2, r2, #4 371#endif 372 str r2, [r0] @ hardware version 373 mov r0, r0 374#ifndef CONFIG_CPU_DCACHE_DISABLE 375 mcr p15, 0, r0, c7, c10, 1 @ clean D entry 376#endif 377 mov pc, lr 378 379 380 __INIT 381 382 .type __arm1026_setup, #function 383__arm1026_setup: 384 mov r0, #0 385 mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 386 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 387 mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 388 mcr p15, 0, r4, c2, c0 @ load page table pointer 389#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 390 mov r0, #4 @ explicitly disable writeback 391 mcr p15, 7, r0, c15, c0, 0 392#endif 393 mrc p15, 0, r0, c1, c0 @ get control register v4 394 ldr r5, arm1026_cr1_clear 395 bic r0, r0, r5 396 ldr r5, arm1026_cr1_set 397 orr r0, r0, r5 398#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN 399 orr r0, r0, #0x4000 @ .R.. .... .... .... 400#endif 401 mov pc, lr 402 .size __arm1026_setup, . - __arm1026_setup 403 404 /* 405 * R 406 * .RVI ZFRS BLDP WCAM 407 * .011 1001 ..11 0101 408 * 409 */ 410 .type arm1026_cr1_clear, #object 411 .type arm1026_cr1_set, #object 412arm1026_cr1_clear: 413 .word 0x7f3f 414arm1026_cr1_set: 415 .word 0x3935 416 417 __INITDATA 418 419/* 420 * Purpose : Function pointers used to access above functions - all calls 421 * come through these 422 */ 423 .type arm1026_processor_functions, #object 424arm1026_processor_functions: 425 .word v5t_early_abort 426 .word cpu_arm1026_proc_init 427 .word cpu_arm1026_proc_fin 428 .word cpu_arm1026_reset 429 .word cpu_arm1026_do_idle 430 .word cpu_arm1026_dcache_clean_area 431 .word cpu_arm1026_switch_mm 432 .word cpu_arm1026_set_pte 433 .size arm1026_processor_functions, . - arm1026_processor_functions 434 435 .section .rodata 436 437 .type cpu_arch_name, #object 438cpu_arch_name: 439 .asciz "armv5tej" 440 .size cpu_arch_name, . - cpu_arch_name 441 442 .type cpu_elf_name, #object 443cpu_elf_name: 444 .asciz "v5" 445 .size cpu_elf_name, . - cpu_elf_name 446 .align 447 448 .type cpu_arm1026_name, #object 449cpu_arm1026_name: 450 .ascii "ARM1026EJ-S" 451#ifndef CONFIG_CPU_ICACHE_DISABLE 452 .ascii "i" 453#endif 454#ifndef CONFIG_CPU_DCACHE_DISABLE 455 .ascii "d" 456#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 457 .ascii "(wt)" 458#else 459 .ascii "(wb)" 460#endif 461#endif 462#ifndef CONFIG_CPU_BPREDICT_DISABLE 463 .ascii "B" 464#endif 465#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN 466 .ascii "RR" 467#endif 468 .ascii "\0" 469 .size cpu_arm1026_name, . - cpu_arm1026_name 470 471 .align 472 473 .section ".proc.info.init", #alloc, #execinstr 474 475 .type __arm1026_proc_info,#object 476__arm1026_proc_info: 477 .long 0x4106a260 @ ARM 1026EJ-S (v5TEJ) 478 .long 0xff0ffff0 479 .long PMD_TYPE_SECT | \ 480 PMD_BIT4 | \ 481 PMD_SECT_AP_WRITE | \ 482 PMD_SECT_AP_READ 483 b __arm1026_setup 484 .long cpu_arch_name 485 .long cpu_elf_name 486 .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA 487 .long cpu_arm1026_name 488 .long arm1026_processor_functions 489 .long v4wbi_tlb_fns 490 .long v4wb_user_fns 491 .long arm1026_cache_fns 492 .size __arm1026_proc_info, . - __arm1026_proc_info 493