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