1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * linux/arch/arm/mm/arm925.S: MMU functions for ARM925 4 * 5 * Copyright (C) 1999,2000 ARM Limited 6 * Copyright (C) 2000 Deep Blue Solutions Ltd. 7 * Copyright (C) 2002 RidgeRun, Inc. 8 * Copyright (C) 2002-2003 MontaVista Software, Inc. 9 * 10 * Update for Linux-2.6 and cache flush improvements 11 * Copyright (C) 2004 Nokia Corporation by Tony Lindgren <tony@atomide.com> 12 * 13 * hacked for non-paged-MM by Hyok S. Choi, 2004. 14 * 15 * These are the low level assembler for performing cache and TLB 16 * functions on the arm925. 17 * 18 * CONFIG_CPU_ARM925_CPU_IDLE -> nohlt 19 * 20 * Some additional notes based on deciphering the TI TRM on OMAP-5910: 21 * 22 * NOTE1: The TI925T Configuration Register bit "D-cache clean and flush 23 * entry mode" must be 0 to flush the entries in both segments 24 * at once. This is the default value. See TRM 2-20 and 2-24 for 25 * more information. 26 * 27 * NOTE2: Default is the "D-cache clean and flush entry mode". It looks 28 * like the "Transparent mode" must be on for partial cache flushes 29 * to work in this mode. This mode only works with 16-bit external 30 * memory. See TRM 2-24 for more information. 31 * 32 * NOTE3: Write-back cache flushing seems to be flakey with devices using 33 * direct memory access, such as USB OHCI. The workaround is to use 34 * write-through cache with CONFIG_CPU_DCACHE_WRITETHROUGH (this is 35 * the default for OMAP-1510). 36 */ 37 38 #include <linux/linkage.h> 39 #include <linux/init.h> 40 #include <linux/cfi_types.h> 41 #include <linux/pgtable.h> 42 #include <asm/assembler.h> 43 #include <asm/hwcap.h> 44 #include <asm/pgtable-hwdef.h> 45 #include <asm/page.h> 46 #include <asm/ptrace.h> 47 #include "proc-macros.S" 48 49 /* 50 * The size of one data cache line. 51 */ 52 #define CACHE_DLINESIZE 16 53 54 /* 55 * The number of data cache segments. 56 */ 57 #define CACHE_DSEGMENTS 2 58 59 /* 60 * The number of lines in a cache segment. 61 */ 62 #define CACHE_DENTRIES 256 63 64 /* 65 * This is the size at which it becomes more efficient to 66 * clean the whole cache, rather than using the individual 67 * cache line maintenance instructions. 68 */ 69 #define CACHE_DLIMIT 8192 70 71 .text 72 /* 73 * cpu_arm925_proc_init() 74 */ 75 SYM_TYPED_FUNC_START(cpu_arm925_proc_init) 76 ret lr 77 SYM_FUNC_END(cpu_arm925_proc_init) 78 79 /* 80 * cpu_arm925_proc_fin() 81 */ 82 SYM_TYPED_FUNC_START(cpu_arm925_proc_fin) 83 mrc p15, 0, r0, c1, c0, 0 @ ctrl register 84 bic r0, r0, #0x1000 @ ...i............ 85 bic r0, r0, #0x000e @ ............wca. 86 mcr p15, 0, r0, c1, c0, 0 @ disable caches 87 ret lr 88 SYM_FUNC_END(cpu_arm925_proc_fin) 89 90 /* 91 * cpu_arm925_reset(loc) 92 * 93 * Perform a soft reset of the system. Put the CPU into the 94 * same state as it would be if it had been reset, and branch 95 * to what would be the reset vector. 96 * 97 * loc: location to jump to for soft reset 98 */ 99 .align 5 100 .pushsection .idmap.text, "ax" 101 SYM_TYPED_FUNC_START(cpu_arm925_reset) 102 /* Send software reset to MPU and DSP */ 103 mov ip, #0xff000000 104 orr ip, ip, #0x00fe0000 105 orr ip, ip, #0x0000ce00 106 mov r4, #1 107 strh r4, [ip, #0x10] 108 SYM_FUNC_END(cpu_arm925_reset) 109 .popsection 110 111 mov ip, #0 112 mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches 113 mcr p15, 0, ip, c7, c10, 4 @ drain WB 114 #ifdef CONFIG_MMU 115 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs 116 #endif 117 mrc p15, 0, ip, c1, c0, 0 @ ctrl register 118 bic ip, ip, #0x000f @ ............wcam 119 bic ip, ip, #0x1100 @ ...i...s........ 120 mcr p15, 0, ip, c1, c0, 0 @ ctrl register 121 ret r0 122 123 /* 124 * cpu_arm925_do_idle() 125 * 126 * Called with IRQs disabled 127 */ 128 .align 10 129 SYM_TYPED_FUNC_START(cpu_arm925_do_idle) 130 mov r0, #0 131 mrc p15, 0, r1, c1, c0, 0 @ Read control register 132 mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer 133 bic r2, r1, #1 << 12 134 mcr p15, 0, r2, c1, c0, 0 @ Disable I cache 135 mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt 136 mcr p15, 0, r1, c1, c0, 0 @ Restore ICache enable 137 ret lr 138 SYM_FUNC_END(cpu_arm925_do_idle) 139 140 /* 141 * flush_icache_all() 142 * 143 * Unconditionally clean and invalidate the entire icache. 144 */ 145 SYM_TYPED_FUNC_START(arm925_flush_icache_all) 146 mov r0, #0 147 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 148 ret lr 149 SYM_FUNC_END(arm925_flush_icache_all) 150 151 /* 152 * flush_user_cache_all() 153 * 154 * Clean and invalidate all cache entries in a particular 155 * address space. 156 */ 157 SYM_FUNC_ALIAS(arm925_flush_user_cache_all, arm925_flush_kern_cache_all) 158 159 /* 160 * flush_kern_cache_all() 161 * 162 * Clean and invalidate the entire cache. 163 */ 164 SYM_TYPED_FUNC_START(arm925_flush_kern_cache_all) 165 mov r2, #VM_EXEC 166 mov ip, #0 167 __flush_whole_cache: 168 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 169 mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache 170 #else 171 /* Flush entries in both segments at once, see NOTE1 above */ 172 mov r3, #(CACHE_DENTRIES - 1) << 4 @ 256 entries in segment 173 2: mcr p15, 0, r3, c7, c14, 2 @ clean+invalidate D index 174 subs r3, r3, #1 << 4 175 bcs 2b @ entries 255 to 0 176 #endif 177 tst r2, #VM_EXEC 178 mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache 179 mcrne p15, 0, ip, c7, c10, 4 @ drain WB 180 ret lr 181 SYM_FUNC_END(arm925_flush_kern_cache_all) 182 183 /* 184 * flush_user_cache_range(start, end, flags) 185 * 186 * Clean and invalidate a range of cache entries in the 187 * specified address range. 188 * 189 * - start - start address (inclusive) 190 * - end - end address (exclusive) 191 * - flags - vm_flags describing address space 192 */ 193 SYM_TYPED_FUNC_START(arm925_flush_user_cache_range) 194 mov ip, #0 195 sub r3, r1, r0 @ calculate total size 196 cmp r3, #CACHE_DLIMIT 197 bgt __flush_whole_cache 198 1: tst r2, #VM_EXEC 199 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 200 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 201 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 202 add r0, r0, #CACHE_DLINESIZE 203 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 204 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 205 add r0, r0, #CACHE_DLINESIZE 206 #else 207 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 208 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 209 add r0, r0, #CACHE_DLINESIZE 210 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 211 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 212 add r0, r0, #CACHE_DLINESIZE 213 #endif 214 cmp r0, r1 215 blo 1b 216 tst r2, #VM_EXEC 217 mcrne p15, 0, ip, c7, c10, 4 @ drain WB 218 ret lr 219 SYM_FUNC_END(arm925_flush_user_cache_range) 220 221 /* 222 * coherent_kern_range(start, end) 223 * 224 * Ensure coherency between the Icache and the Dcache in the 225 * region described by start, end. If you have non-snooping 226 * Harvard caches, you need to implement this function. 227 * 228 * - start - virtual start address 229 * - end - virtual end address 230 */ 231 SYM_TYPED_FUNC_START(arm925_coherent_kern_range) 232 #ifdef CONFIG_CFI_CLANG /* Fallthrough if !CFI */ 233 b arm925_coherent_user_range 234 #endif 235 SYM_FUNC_END(arm925_coherent_kern_range) 236 237 /* 238 * coherent_user_range(start, end) 239 * 240 * Ensure coherency between the Icache and the Dcache in the 241 * region described by start, end. If you have non-snooping 242 * Harvard caches, you need to implement this function. 243 * 244 * - start - virtual start address 245 * - end - virtual end address 246 */ 247 SYM_TYPED_FUNC_START(arm925_coherent_user_range) 248 bic r0, r0, #CACHE_DLINESIZE - 1 249 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 250 mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry 251 add r0, r0, #CACHE_DLINESIZE 252 cmp r0, r1 253 blo 1b 254 mcr p15, 0, r0, c7, c10, 4 @ drain WB 255 mov r0, #0 256 ret lr 257 SYM_FUNC_END(arm925_coherent_user_range) 258 259 /* 260 * flush_kern_dcache_area(void *addr, size_t size) 261 * 262 * Ensure no D cache aliasing occurs, either with itself or 263 * the I cache 264 * 265 * - addr - kernel address 266 * - size - region size 267 */ 268 SYM_TYPED_FUNC_START(arm925_flush_kern_dcache_area) 269 add r1, r0, r1 270 1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry 271 add r0, r0, #CACHE_DLINESIZE 272 cmp r0, r1 273 blo 1b 274 mov r0, #0 275 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 276 mcr p15, 0, r0, c7, c10, 4 @ drain WB 277 ret lr 278 SYM_FUNC_END(arm925_flush_kern_dcache_area) 279 280 /* 281 * dma_inv_range(start, end) 282 * 283 * Invalidate (discard) the specified virtual address range. 284 * May not write back any entries. If 'start' or 'end' 285 * are not cache line aligned, those lines must be written 286 * back. 287 * 288 * - start - virtual start address 289 * - end - virtual end address 290 * 291 * (same as v4wb) 292 */ 293 arm925_dma_inv_range: 294 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 295 tst r0, #CACHE_DLINESIZE - 1 296 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry 297 tst r1, #CACHE_DLINESIZE - 1 298 mcrne p15, 0, r1, c7, c10, 1 @ clean D entry 299 #endif 300 bic r0, r0, #CACHE_DLINESIZE - 1 301 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 302 add r0, r0, #CACHE_DLINESIZE 303 cmp r0, r1 304 blo 1b 305 mcr p15, 0, r0, c7, c10, 4 @ drain WB 306 ret lr 307 308 /* 309 * dma_clean_range(start, end) 310 * 311 * Clean the specified virtual address range. 312 * 313 * - start - virtual start address 314 * - end - virtual end address 315 * 316 * (same as v4wb) 317 */ 318 arm925_dma_clean_range: 319 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 320 bic r0, r0, #CACHE_DLINESIZE - 1 321 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 322 add r0, r0, #CACHE_DLINESIZE 323 cmp r0, r1 324 blo 1b 325 #endif 326 mcr p15, 0, r0, c7, c10, 4 @ drain WB 327 ret lr 328 329 /* 330 * dma_flush_range(start, end) 331 * 332 * Clean and invalidate the specified virtual address range. 333 * 334 * - start - virtual start address 335 * - end - virtual end address 336 */ 337 SYM_TYPED_FUNC_START(arm925_dma_flush_range) 338 bic r0, r0, #CACHE_DLINESIZE - 1 339 1: 340 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 341 mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry 342 #else 343 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 344 #endif 345 add r0, r0, #CACHE_DLINESIZE 346 cmp r0, r1 347 blo 1b 348 mcr p15, 0, r0, c7, c10, 4 @ drain WB 349 ret lr 350 SYM_FUNC_END(arm925_dma_flush_range) 351 352 /* 353 * dma_map_area(start, size, dir) 354 * - start - kernel virtual start address 355 * - size - size of region 356 * - dir - DMA direction 357 */ 358 SYM_TYPED_FUNC_START(arm925_dma_map_area) 359 add r1, r1, r0 360 cmp r2, #DMA_TO_DEVICE 361 beq arm925_dma_clean_range 362 bcs arm925_dma_inv_range 363 b arm925_dma_flush_range 364 SYM_FUNC_END(arm925_dma_map_area) 365 366 /* 367 * dma_unmap_area(start, size, dir) 368 * - start - kernel virtual start address 369 * - size - size of region 370 * - dir - DMA direction 371 */ 372 SYM_TYPED_FUNC_START(arm925_dma_unmap_area) 373 ret lr 374 SYM_FUNC_END(arm925_dma_unmap_area) 375 376 SYM_TYPED_FUNC_START(cpu_arm925_dcache_clean_area) 377 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 378 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 379 add r0, r0, #CACHE_DLINESIZE 380 subs r1, r1, #CACHE_DLINESIZE 381 bhi 1b 382 #endif 383 mcr p15, 0, r0, c7, c10, 4 @ drain WB 384 ret lr 385 SYM_FUNC_END(cpu_arm925_dcache_clean_area) 386 387 /* =============================== PageTable ============================== */ 388 389 /* 390 * cpu_arm925_switch_mm(pgd) 391 * 392 * Set the translation base pointer to be as described by pgd. 393 * 394 * pgd: new page tables 395 */ 396 .align 5 397 SYM_TYPED_FUNC_START(cpu_arm925_switch_mm) 398 #ifdef CONFIG_MMU 399 mov ip, #0 400 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 401 mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache 402 #else 403 /* Flush entries in bothe segments at once, see NOTE1 above */ 404 mov r3, #(CACHE_DENTRIES - 1) << 4 @ 256 entries in segment 405 2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index 406 subs r3, r3, #1 << 4 407 bcs 2b @ entries 255 to 0 408 #endif 409 mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache 410 mcr p15, 0, ip, c7, c10, 4 @ drain WB 411 mcr p15, 0, r0, c2, c0, 0 @ load page table pointer 412 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs 413 #endif 414 ret lr 415 SYM_FUNC_END(cpu_arm925_switch_mm) 416 417 /* 418 * cpu_arm925_set_pte_ext(ptep, pte, ext) 419 * 420 * Set a PTE and flush it out 421 */ 422 .align 5 423 SYM_TYPED_FUNC_START(cpu_arm925_set_pte_ext) 424 #ifdef CONFIG_MMU 425 armv3_set_pte_ext 426 mov r0, r0 427 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH 428 mcr p15, 0, r0, c7, c10, 1 @ clean D entry 429 #endif 430 mcr p15, 0, r0, c7, c10, 4 @ drain WB 431 #endif /* CONFIG_MMU */ 432 ret lr 433 SYM_FUNC_END(cpu_arm925_set_pte_ext) 434 435 .type __arm925_setup, #function 436 __arm925_setup: 437 mov r0, #0 438 439 /* Transparent on, D-cache clean & flush mode. See NOTE2 above */ 440 orr r0,r0,#1 << 1 @ transparent mode on 441 mcr p15, 0, r0, c15, c1, 0 @ write TI config register 442 443 mov r0, #0 444 mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 445 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 446 #ifdef CONFIG_MMU 447 mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 448 #endif 449 450 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 451 mov r0, #4 @ disable write-back on caches explicitly 452 mcr p15, 7, r0, c15, c0, 0 453 #endif 454 455 adr r5, arm925_crval 456 ldmia r5, {r5, r6} 457 mrc p15, 0, r0, c1, c0 @ get control register v4 458 bic r0, r0, r5 459 orr r0, r0, r6 460 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN 461 orr r0, r0, #0x4000 @ .1.. .... .... .... 462 #endif 463 ret lr 464 .size __arm925_setup, . - __arm925_setup 465 466 /* 467 * R 468 * .RVI ZFRS BLDP WCAM 469 * .011 0001 ..11 1101 470 * 471 */ 472 .type arm925_crval, #object 473 arm925_crval: 474 crval clear=0x00007f3f, mmuset=0x0000313d, ucset=0x00001130 475 476 __INITDATA 477 @ define struct processor (see <asm/proc-fns.h> and proc-macros.S) 478 define_processor_functions arm925, dabort=v4t_early_abort, pabort=legacy_pabort 479 480 .section ".rodata" 481 482 string cpu_arch_name, "armv4t" 483 string cpu_elf_name, "v4" 484 string cpu_arm925_name, "ARM925T" 485 486 .align 487 488 .section ".proc.info.init", "a" 489 490 .macro arm925_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cache 491 .type __\name\()_proc_info,#object 492 __\name\()_proc_info: 493 .long \cpu_val 494 .long \cpu_mask 495 .long PMD_TYPE_SECT | \ 496 PMD_SECT_CACHEABLE | \ 497 PMD_BIT4 | \ 498 PMD_SECT_AP_WRITE | \ 499 PMD_SECT_AP_READ 500 .long PMD_TYPE_SECT | \ 501 PMD_BIT4 | \ 502 PMD_SECT_AP_WRITE | \ 503 PMD_SECT_AP_READ 504 initfn __arm925_setup, __\name\()_proc_info 505 .long cpu_arch_name 506 .long cpu_elf_name 507 .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB 508 .long cpu_arm925_name 509 .long arm925_processor_functions 510 .long v4wbi_tlb_fns 511 .long v4wb_user_fns 512 .long arm925_cache_fns 513 .size __\name\()_proc_info, . - __\name\()_proc_info 514 .endm 515 516 arm925_proc_info arm925, 0x54029250, 0xfffffff0, cpu_arm925_name 517 arm925_proc_info arm915, 0x54029150, 0xfffffff0, cpu_arm925_name
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.