1/* SPDX-License-Identifier: GPL-2.0-or-later */ 2/* 3 * linux/arch/arm/mm/proc-arm926.S: MMU functions for ARM926EJ-S 4 * 5 * Copyright (C) 1999-2001 ARM Limited 6 * Copyright (C) 2000 Deep Blue Solutions Ltd. 7 * hacked for non-paged-MM by Hyok S. Choi, 2003. 8 * 9 * These are the low level assembler for performing cache and TLB 10 * functions on the arm926. 11 * 12 * CONFIG_CPU_ARM926_CPU_IDLE -> nohlt 13 */ 14#include <linux/linkage.h> 15#include <linux/init.h> 16#include <asm/assembler.h> 17#include <asm/hwcap.h> 18#include <asm/pgtable-hwdef.h> 19#include <asm/pgtable.h> 20#include <asm/page.h> 21#include <asm/ptrace.h> 22#include "proc-macros.S" 23 24/* 25 * This is the maximum size of an area which will be invalidated 26 * using the single invalidate entry instructions. Anything larger 27 * than this, and we go for the whole cache. 28 * 29 * This value should be chosen such that we choose the cheapest 30 * alternative. 31 */ 32#define CACHE_DLIMIT 16384 33 34/* 35 * the cache line size of the I and D cache 36 */ 37#define CACHE_DLINESIZE 32 38 39 .text 40/* 41 * cpu_arm926_proc_init() 42 */ 43ENTRY(cpu_arm926_proc_init) 44 ret lr 45 46/* 47 * cpu_arm926_proc_fin() 48 */ 49ENTRY(cpu_arm926_proc_fin) 50 mrc p15, 0, r0, c1, c0, 0 @ ctrl register 51 bic r0, r0, #0x1000 @ ...i............ 52 bic r0, r0, #0x000e @ ............wca. 53 mcr p15, 0, r0, c1, c0, 0 @ disable caches 54 ret lr 55 56/* 57 * cpu_arm926_reset(loc) 58 * 59 * Perform a soft reset of the system. Put the CPU into the 60 * same state as it would be if it had been reset, and branch 61 * to what would be the reset vector. 62 * 63 * loc: location to jump to for soft reset 64 */ 65 .align 5 66 .pushsection .idmap.text, "ax" 67ENTRY(cpu_arm926_reset) 68 mov ip, #0 69 mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches 70 mcr p15, 0, ip, c7, c10, 4 @ drain WB 71#ifdef CONFIG_MMU 72 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs 73#endif 74 mrc p15, 0, ip, c1, c0, 0 @ ctrl register 75 bic ip, ip, #0x000f @ ............wcam 76 bic ip, ip, #0x1100 @ ...i...s........ 77 mcr p15, 0, ip, c1, c0, 0 @ ctrl register 78 ret r0 79ENDPROC(cpu_arm926_reset) 80 .popsection 81 82/* 83 * cpu_arm926_do_idle() 84 * 85 * Called with IRQs disabled 86 */ 87 .align 10 88ENTRY(cpu_arm926_do_idle) 89 mov r0, #0 90 mrc p15, 0, r1, c1, c0, 0 @ Read control register 91 mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer 92 bic r2, r1, #1 << 12 93 mrs r3, cpsr @ Disable FIQs while Icache 94 orr ip, r3, #PSR_F_BIT @ is disabled 95 msr cpsr_c, ip 96 mcr p15, 0, r2, c1, c0, 0 @ Disable I cache 97 mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt 98 mcr p15, 0, r1, c1, c0, 0 @ Restore ICache enable 99 msr cpsr_c, r3 @ Restore FIQ state 100 ret lr 101 102/* 103 * flush_icache_all() 104 * 105 * Unconditionally clean and invalidate the entire icache. 106 */ 107ENTRY(arm926_flush_icache_all) 108 mov r0, #0 109 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 110 ret lr 111ENDPROC(arm926_flush_icache_all) 112 113/* 114 * flush_user_cache_all() 115 * 116 * Clean and invalidate all cache entries in a particular 117 * address space. 118 */ 119ENTRY(arm926_flush_user_cache_all) 120 /* FALLTHROUGH */ 121 122/* 123 * flush_kern_cache_all() 124 * 125 * Clean and invalidate the entire cache. 126 */ 127ENTRY(arm926_flush_kern_cache_all) 128 mov r2, #VM_EXEC 129 mov ip, #0 130__flush_whole_cache: 131#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 132 mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache 133#else 1341: mrc p15, 0, APSR_nzcv, c7, c14, 3 @ test,clean,invalidate 135 bne 1b 136#endif 137 tst r2, #VM_EXEC 138 mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache 139 mcrne p15, 0, ip, c7, c10, 4 @ drain WB 140 ret lr 141 142/* 143 * flush_user_cache_range(start, end, flags) 144 * 145 * Clean and invalidate a range of cache entries in the 146 * specified address range. 147 * 148 * - start - start address (inclusive) 149 * - end - end address (exclusive) 150 * - flags - vm_flags describing address space 151 */ 152ENTRY(arm926_flush_user_cache_range) 153 mov ip, #0 154 sub r3, r1, r0 @ calculate total size 155 cmp r3, #CACHE_DLIMIT 156 bgt __flush_whole_cache 1571: tst r2, #VM_EXEC 158#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 159 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 160 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 161 add r0, r0, #CACHE_DLINESIZE 162 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 163 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 164 add r0, r0, #CACHE_DLINESIZE 165#else 166 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 167 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 168 add r0, r0, #CACHE_DLINESIZE 169 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 170 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 171 add r0, r0, #CACHE_DLINESIZE 172#endif 173 cmp r0, r1 174 blo 1b 175 tst r2, #VM_EXEC 176 mcrne p15, 0, ip, c7, c10, 4 @ drain WB 177 ret lr 178 179/* 180 * coherent_kern_range(start, end) 181 * 182 * Ensure coherency between the Icache and the Dcache in the 183 * region described by start, end. If you have non-snooping 184 * Harvard caches, you need to implement this function. 185 * 186 * - start - virtual start address 187 * - end - virtual end address 188 */ 189ENTRY(arm926_coherent_kern_range) 190 /* FALLTHROUGH */ 191 192/* 193 * coherent_user_range(start, end) 194 * 195 * Ensure coherency between the Icache and the Dcache in the 196 * region described by start, end. If you have non-snooping 197 * Harvard caches, you need to implement this function. 198 * 199 * - start - virtual start address 200 * - end - virtual end address 201 */ 202ENTRY(arm926_coherent_user_range) 203 bic r0, r0, #CACHE_DLINESIZE - 1 2041: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 205 mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry 206 add r0, r0, #CACHE_DLINESIZE 207 cmp r0, r1 208 blo 1b 209 mcr p15, 0, r0, c7, c10, 4 @ drain WB 210 mov r0, #0 211 ret lr 212 213/* 214 * flush_kern_dcache_area(void *addr, size_t size) 215 * 216 * Ensure no D cache aliasing occurs, either with itself or 217 * the I cache 218 * 219 * - addr - kernel address 220 * - size - region size 221 */ 222ENTRY(arm926_flush_kern_dcache_area) 223 add r1, r0, r1 2241: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry 225 add r0, r0, #CACHE_DLINESIZE 226 cmp r0, r1 227 blo 1b 228 mov r0, #0 229 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 230 mcr p15, 0, r0, c7, c10, 4 @ drain WB 231 ret lr 232 233/* 234 * dma_inv_range(start, end) 235 * 236 * Invalidate (discard) the specified virtual address range. 237 * May not write back any entries. If 'start' or 'end' 238 * are not cache line aligned, those lines must be written 239 * back. 240 * 241 * - start - virtual start address 242 * - end - virtual end address 243 * 244 * (same as v4wb) 245 */ 246arm926_dma_inv_range: 247#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 248 tst r0, #CACHE_DLINESIZE - 1 249 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry 250 tst r1, #CACHE_DLINESIZE - 1 251 mcrne p15, 0, r1, c7, c10, 1 @ clean D entry 252#endif 253 bic r0, r0, #CACHE_DLINESIZE - 1 2541: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 255 add r0, r0, #CACHE_DLINESIZE 256 cmp r0, r1 257 blo 1b 258 mcr p15, 0, r0, c7, c10, 4 @ drain WB 259 ret lr 260 261/* 262 * dma_clean_range(start, end) 263 * 264 * Clean the specified virtual address range. 265 * 266 * - start - virtual start address 267 * - end - virtual end address 268 * 269 * (same as v4wb) 270 */ 271arm926_dma_clean_range: 272#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 273 bic r0, r0, #CACHE_DLINESIZE - 1 2741: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 275 add r0, r0, #CACHE_DLINESIZE 276 cmp r0, r1 277 blo 1b 278#endif 279 mcr p15, 0, r0, c7, c10, 4 @ drain WB 280 ret lr 281 282/* 283 * dma_flush_range(start, end) 284 * 285 * Clean and invalidate the specified virtual address range. 286 * 287 * - start - virtual start address 288 * - end - virtual end address 289 */ 290ENTRY(arm926_dma_flush_range) 291 bic r0, r0, #CACHE_DLINESIZE - 1 2921: 293#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 294 mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry 295#else 296 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 297#endif 298 add r0, r0, #CACHE_DLINESIZE 299 cmp r0, r1 300 blo 1b 301 mcr p15, 0, r0, c7, c10, 4 @ drain WB 302 ret lr 303 304/* 305 * dma_map_area(start, size, dir) 306 * - start - kernel virtual start address 307 * - size - size of region 308 * - dir - DMA direction 309 */ 310ENTRY(arm926_dma_map_area) 311 add r1, r1, r0 312 cmp r2, #DMA_TO_DEVICE 313 beq arm926_dma_clean_range 314 bcs arm926_dma_inv_range 315 b arm926_dma_flush_range 316ENDPROC(arm926_dma_map_area) 317 318/* 319 * dma_unmap_area(start, size, dir) 320 * - start - kernel virtual start address 321 * - size - size of region 322 * - dir - DMA direction 323 */ 324ENTRY(arm926_dma_unmap_area) 325 ret lr 326ENDPROC(arm926_dma_unmap_area) 327 328 .globl arm926_flush_kern_cache_louis 329 .equ arm926_flush_kern_cache_louis, arm926_flush_kern_cache_all 330 331 @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) 332 define_cache_functions arm926 333 334ENTRY(cpu_arm926_dcache_clean_area) 335#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 3361: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 337 add r0, r0, #CACHE_DLINESIZE 338 subs r1, r1, #CACHE_DLINESIZE 339 bhi 1b 340#endif 341 mcr p15, 0, r0, c7, c10, 4 @ drain WB 342 ret lr 343 344/* =============================== PageTable ============================== */ 345 346/* 347 * cpu_arm926_switch_mm(pgd) 348 * 349 * Set the translation base pointer to be as described by pgd. 350 * 351 * pgd: new page tables 352 */ 353 .align 5 354ENTRY(cpu_arm926_switch_mm) 355#ifdef CONFIG_MMU 356 mov ip, #0 357#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 358 mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache 359#else 360@ && 'Clean & Invalidate whole DCache' 3611: mrc p15, 0, APSR_nzcv, c7, c14, 3 @ test,clean,invalidate 362 bne 1b 363#endif 364 mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache 365 mcr p15, 0, ip, c7, c10, 4 @ drain WB 366 mcr p15, 0, r0, c2, c0, 0 @ load page table pointer 367 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs 368#endif 369 ret lr 370 371/* 372 * cpu_arm926_set_pte_ext(ptep, pte, ext) 373 * 374 * Set a PTE and flush it out 375 */ 376 .align 5 377ENTRY(cpu_arm926_set_pte_ext) 378#ifdef CONFIG_MMU 379 armv3_set_pte_ext 380 mov r0, r0 381#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 382 mcr p15, 0, r0, c7, c10, 1 @ clean D entry 383#endif 384 mcr p15, 0, r0, c7, c10, 4 @ drain WB 385#endif 386 ret lr 387 388/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */ 389.globl cpu_arm926_suspend_size 390.equ cpu_arm926_suspend_size, 4 * 3 391#ifdef CONFIG_ARM_CPU_SUSPEND 392ENTRY(cpu_arm926_do_suspend) 393 stmfd sp!, {r4 - r6, lr} 394 mrc p15, 0, r4, c13, c0, 0 @ PID 395 mrc p15, 0, r5, c3, c0, 0 @ Domain ID 396 mrc p15, 0, r6, c1, c0, 0 @ Control register 397 stmia r0, {r4 - r6} 398 ldmfd sp!, {r4 - r6, pc} 399ENDPROC(cpu_arm926_do_suspend) 400 401ENTRY(cpu_arm926_do_resume) 402 mov ip, #0 403 mcr p15, 0, ip, c8, c7, 0 @ invalidate I+D TLBs 404 mcr p15, 0, ip, c7, c7, 0 @ invalidate I+D caches 405 ldmia r0, {r4 - r6} 406 mcr p15, 0, r4, c13, c0, 0 @ PID 407 mcr p15, 0, r5, c3, c0, 0 @ Domain ID 408 mcr p15, 0, r1, c2, c0, 0 @ TTB address 409 mov r0, r6 @ control register 410 b cpu_resume_mmu 411ENDPROC(cpu_arm926_do_resume) 412#endif 413 414 .type __arm926_setup, #function 415__arm926_setup: 416 mov r0, #0 417 mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 418 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 419#ifdef CONFIG_MMU 420 mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 421#endif 422 423 424#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 425 mov r0, #4 @ disable write-back on caches explicitly 426 mcr p15, 7, r0, c15, c0, 0 427#endif 428 429 adr r5, arm926_crval 430 ldmia r5, {r5, r6} 431 mrc p15, 0, r0, c1, c0 @ get control register v4 432 bic r0, r0, r5 433 orr r0, r0, r6 434#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN 435 orr r0, r0, #0x4000 @ .1.. .... .... .... 436#endif 437 ret lr 438 .size __arm926_setup, . - __arm926_setup 439 440 /* 441 * R 442 * .RVI ZFRS BLDP WCAM 443 * .011 0001 ..11 0101 444 * 445 */ 446 .type arm926_crval, #object 447arm926_crval: 448 crval clear=0x00007f3f, mmuset=0x00003135, ucset=0x00001134 449 450 __INITDATA 451 452 @ define struct processor (see <asm/proc-fns.h> and proc-macros.S) 453 define_processor_functions arm926, dabort=v5tj_early_abort, pabort=legacy_pabort, suspend=1 454 455 .section ".rodata" 456 457 string cpu_arch_name, "armv5tej" 458 string cpu_elf_name, "v5" 459 string cpu_arm926_name, "ARM926EJ-S" 460 461 .align 462 463 .section ".proc.info.init", "a" 464 465 .type __arm926_proc_info,#object 466__arm926_proc_info: 467 .long 0x41069260 @ ARM926EJ-S (v5TEJ) 468 .long 0xff0ffff0 469 .long PMD_TYPE_SECT | \ 470 PMD_SECT_BUFFERABLE | \ 471 PMD_SECT_CACHEABLE | \ 472 PMD_BIT4 | \ 473 PMD_SECT_AP_WRITE | \ 474 PMD_SECT_AP_READ 475 .long PMD_TYPE_SECT | \ 476 PMD_BIT4 | \ 477 PMD_SECT_AP_WRITE | \ 478 PMD_SECT_AP_READ 479 initfn __arm926_setup, __arm926_proc_info 480 .long cpu_arch_name 481 .long cpu_elf_name 482 .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA 483 .long cpu_arm926_name 484 .long arm926_processor_functions 485 .long v4wbi_tlb_fns 486 .long v4wb_user_fns 487 .long arm926_cache_fns 488 .size __arm926_proc_info, . - __arm926_proc_info 489