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