root/arch/arm/mm/proc-arm946.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0-only */
   2 /*
   3  *  linux/arch/arm/mm/arm946.S: utility functions for ARM946E-S
   4  *
   5  *  Copyright (C) 2004-2006 Hyok S. Choi (hyok.choi@samsung.com)
   6  *
   7  *  (Many of cache codes are from proc-arm926.S)
   8  */
   9 #include <linux/linkage.h>
  10 #include <linux/init.h>
  11 #include <asm/assembler.h>
  12 #include <asm/hwcap.h>
  13 #include <asm/pgtable-hwdef.h>
  14 #include <asm/pgtable.h>
  15 #include <asm/ptrace.h>
  16 #include "proc-macros.S"
  17 
  18 /*
  19  * ARM946E-S is synthesizable to have 0KB to 1MB sized D-Cache,
  20  * comprising 256 lines of 32 bytes (8 words).
  21  */
  22 #define CACHE_DSIZE     (CONFIG_CPU_DCACHE_SIZE) /* typically 8KB. */
  23 #define CACHE_DLINESIZE 32                      /* fixed */
  24 #define CACHE_DSEGMENTS 4                       /* fixed */
  25 #define CACHE_DENTRIES  (CACHE_DSIZE / CACHE_DSEGMENTS / CACHE_DLINESIZE)
  26 #define CACHE_DLIMIT    (CACHE_DSIZE * 4)       /* benchmark needed */
  27 
  28         .text
  29 /*
  30  * cpu_arm946_proc_init()
  31  * cpu_arm946_switch_mm()
  32  *
  33  * These are not required.
  34  */
  35 ENTRY(cpu_arm946_proc_init)
  36 ENTRY(cpu_arm946_switch_mm)
  37         ret     lr
  38 
  39 /*
  40  * cpu_arm946_proc_fin()
  41  */
  42 ENTRY(cpu_arm946_proc_fin)
  43         mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
  44         bic     r0, r0, #0x00001000             @ i-cache
  45         bic     r0, r0, #0x00000004             @ d-cache
  46         mcr     p15, 0, r0, c1, c0, 0           @ disable caches
  47         ret     lr
  48 
  49 /*
  50  * cpu_arm946_reset(loc)
  51  * Params  : r0 = address to jump to
  52  * Notes   : This sets up everything for a reset
  53  */
  54         .pushsection    .idmap.text, "ax"
  55 ENTRY(cpu_arm946_reset)
  56         mov     ip, #0
  57         mcr     p15, 0, ip, c7, c5, 0           @ flush I cache
  58         mcr     p15, 0, ip, c7, c6, 0           @ flush D cache
  59         mcr     p15, 0, ip, c7, c10, 4          @ drain WB
  60         mrc     p15, 0, ip, c1, c0, 0           @ ctrl register
  61         bic     ip, ip, #0x00000005             @ .............c.p
  62         bic     ip, ip, #0x00001000             @ i-cache
  63         mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
  64         ret     r0
  65 ENDPROC(cpu_arm946_reset)
  66         .popsection
  67 
  68 /*
  69  * cpu_arm946_do_idle()
  70  */
  71         .align  5
  72 ENTRY(cpu_arm946_do_idle)
  73         mcr     p15, 0, r0, c7, c0, 4           @ Wait for interrupt
  74         ret     lr
  75 
  76 /*
  77  *      flush_icache_all()
  78  *
  79  *      Unconditionally clean and invalidate the entire icache.
  80  */
  81 ENTRY(arm946_flush_icache_all)
  82         mov     r0, #0
  83         mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
  84         ret     lr
  85 ENDPROC(arm946_flush_icache_all)
  86 
  87 /*
  88  *      flush_user_cache_all()
  89  */
  90 ENTRY(arm946_flush_user_cache_all)
  91         /* FALLTHROUGH */
  92 
  93 /*
  94  *      flush_kern_cache_all()
  95  *
  96  *      Clean and invalidate the entire cache.
  97  */
  98 ENTRY(arm946_flush_kern_cache_all)
  99         mov     r2, #VM_EXEC
 100         mov     ip, #0
 101 __flush_whole_cache:
 102 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 103         mcr     p15, 0, ip, c7, c6, 0           @ flush D cache
 104 #else
 105         mov     r1, #(CACHE_DSEGMENTS - 1) << 29 @ 4 segments
 106 1:      orr     r3, r1, #(CACHE_DENTRIES - 1) << 4 @ n entries
 107 2:      mcr     p15, 0, r3, c7, c14, 2          @ clean/flush D index
 108         subs    r3, r3, #1 << 4
 109         bcs     2b                              @ entries n to 0
 110         subs    r1, r1, #1 << 29
 111         bcs     1b                              @ segments 3 to 0
 112 #endif
 113         tst     r2, #VM_EXEC
 114         mcrne   p15, 0, ip, c7, c5, 0           @ flush I cache
 115         mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
 116         ret     lr
 117 
 118 /*
 119  *      flush_user_cache_range(start, end, flags)
 120  *
 121  *      Clean and invalidate a range of cache entries in the
 122  *      specified address range.
 123  *
 124  *      - start - start address (inclusive)
 125  *      - end   - end address (exclusive)
 126  *      - flags - vm_flags describing address space
 127  * (same as arm926)
 128  */
 129 ENTRY(arm946_flush_user_cache_range)
 130         mov     ip, #0
 131         sub     r3, r1, r0                      @ calculate total size
 132         cmp     r3, #CACHE_DLIMIT
 133         bhs     __flush_whole_cache
 134 
 135 1:      tst     r2, #VM_EXEC
 136 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 137         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
 138         mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
 139         add     r0, r0, #CACHE_DLINESIZE
 140         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
 141         mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
 142         add     r0, r0, #CACHE_DLINESIZE
 143 #else
 144         mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
 145         mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
 146         add     r0, r0, #CACHE_DLINESIZE
 147         mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
 148         mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
 149         add     r0, r0, #CACHE_DLINESIZE
 150 #endif
 151         cmp     r0, r1
 152         blo     1b
 153         tst     r2, #VM_EXEC
 154         mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
 155         ret     lr
 156 
 157 /*
 158  *      coherent_kern_range(start, end)
 159  *
 160  *      Ensure coherency between the Icache and the Dcache in the
 161  *      region described by start, end.  If you have non-snooping
 162  *      Harvard caches, you need to implement this function.
 163  *
 164  *      - start - virtual start address
 165  *      - end   - virtual end address
 166  */
 167 ENTRY(arm946_coherent_kern_range)
 168         /* FALLTHROUGH */
 169 
 170 /*
 171  *      coherent_user_range(start, end)
 172  *
 173  *      Ensure coherency between the Icache and the Dcache in the
 174  *      region described by start, end.  If you have non-snooping
 175  *      Harvard caches, you need to implement this function.
 176  *
 177  *      - start - virtual start address
 178  *      - end   - virtual end address
 179  * (same as arm926)
 180  */
 181 ENTRY(arm946_coherent_user_range)
 182         bic     r0, r0, #CACHE_DLINESIZE - 1
 183 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
 184         mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
 185         add     r0, r0, #CACHE_DLINESIZE
 186         cmp     r0, r1
 187         blo     1b
 188         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 189         mov     r0, #0
 190         ret     lr
 191 
 192 /*
 193  *      flush_kern_dcache_area(void *addr, size_t size)
 194  *
 195  *      Ensure no D cache aliasing occurs, either with itself or
 196  *      the I cache
 197  *
 198  *      - addr  - kernel address
 199  *      - size  - region size
 200  * (same as arm926)
 201  */
 202 ENTRY(arm946_flush_kern_dcache_area)
 203         add     r1, r0, r1
 204 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
 205         add     r0, r0, #CACHE_DLINESIZE
 206         cmp     r0, r1
 207         blo     1b
 208         mov     r0, #0
 209         mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
 210         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 211         ret     lr
 212 
 213 /*
 214  *      dma_inv_range(start, end)
 215  *
 216  *      Invalidate (discard) the specified virtual address range.
 217  *      May not write back any entries.  If 'start' or 'end'
 218  *      are not cache line aligned, those lines must be written
 219  *      back.
 220  *
 221  *      - start - virtual start address
 222  *      - end   - virtual end address
 223  * (same as arm926)
 224  */
 225 arm946_dma_inv_range:
 226 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 227         tst     r0, #CACHE_DLINESIZE - 1
 228         mcrne   p15, 0, r0, c7, c10, 1          @ clean D entry
 229         tst     r1, #CACHE_DLINESIZE - 1
 230         mcrne   p15, 0, r1, c7, c10, 1          @ clean D entry
 231 #endif
 232         bic     r0, r0, #CACHE_DLINESIZE - 1
 233 1:      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
 234         add     r0, r0, #CACHE_DLINESIZE
 235         cmp     r0, r1
 236         blo     1b
 237         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 238         ret     lr
 239 
 240 /*
 241  *      dma_clean_range(start, end)
 242  *
 243  *      Clean the specified virtual address range.
 244  *
 245  *      - start - virtual start address
 246  *      - end   - virtual end address
 247  *
 248  * (same as arm926)
 249  */
 250 arm946_dma_clean_range:
 251 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 252         bic     r0, r0, #CACHE_DLINESIZE - 1
 253 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
 254         add     r0, r0, #CACHE_DLINESIZE
 255         cmp     r0, r1
 256         blo     1b
 257 #endif
 258         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 259         ret     lr
 260 
 261 /*
 262  *      dma_flush_range(start, end)
 263  *
 264  *      Clean and invalidate the specified virtual address range.
 265  *
 266  *      - start - virtual start address
 267  *      - end   - virtual end address
 268  *
 269  * (same as arm926)
 270  */
 271 ENTRY(arm946_dma_flush_range)
 272         bic     r0, r0, #CACHE_DLINESIZE - 1
 273 1:
 274 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 275         mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
 276 #else
 277         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
 278 #endif
 279         add     r0, r0, #CACHE_DLINESIZE
 280         cmp     r0, r1
 281         blo     1b
 282         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 283         ret     lr
 284 
 285 /*
 286  *      dma_map_area(start, size, dir)
 287  *      - start - kernel virtual start address
 288  *      - size  - size of region
 289  *      - dir   - DMA direction
 290  */
 291 ENTRY(arm946_dma_map_area)
 292         add     r1, r1, r0
 293         cmp     r2, #DMA_TO_DEVICE
 294         beq     arm946_dma_clean_range
 295         bcs     arm946_dma_inv_range
 296         b       arm946_dma_flush_range
 297 ENDPROC(arm946_dma_map_area)
 298 
 299 /*
 300  *      dma_unmap_area(start, size, dir)
 301  *      - start - kernel virtual start address
 302  *      - size  - size of region
 303  *      - dir   - DMA direction
 304  */
 305 ENTRY(arm946_dma_unmap_area)
 306         ret     lr
 307 ENDPROC(arm946_dma_unmap_area)
 308 
 309         .globl  arm946_flush_kern_cache_louis
 310         .equ    arm946_flush_kern_cache_louis, arm946_flush_kern_cache_all
 311 
 312         @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
 313         define_cache_functions arm946
 314 
 315 ENTRY(cpu_arm946_dcache_clean_area)
 316 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 317 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
 318         add     r0, r0, #CACHE_DLINESIZE
 319         subs    r1, r1, #CACHE_DLINESIZE
 320         bhi     1b
 321 #endif
 322         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 323         ret     lr
 324 
 325         .type   __arm946_setup, #function
 326 __arm946_setup:
 327         mov     r0, #0
 328         mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
 329         mcr     p15, 0, r0, c7, c6, 0           @ invalidate D cache
 330         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 331 
 332         mcr     p15, 0, r0, c6, c3, 0           @ disable memory region 3~7
 333         mcr     p15, 0, r0, c6, c4, 0
 334         mcr     p15, 0, r0, c6, c5, 0
 335         mcr     p15, 0, r0, c6, c6, 0
 336         mcr     p15, 0, r0, c6, c7, 0
 337 
 338         mov     r0, #0x0000003F                 @ base = 0, size = 4GB
 339         mcr     p15, 0, r0, c6, c0, 0           @ set region 0, default
 340 
 341         ldr     r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM
 342         ldr     r7, =CONFIG_DRAM_SIZE           @ size of RAM (must be >= 4KB)
 343         pr_val  r3, r0, r7, #1
 344         mcr     p15, 0, r3, c6, c1, 0
 345 
 346         ldr     r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of FLASH
 347         ldr     r7, =CONFIG_FLASH_SIZE          @ size of FLASH (must be >= 4KB)
 348         pr_val  r3, r0, r7, #1
 349         mcr     p15, 0, r3, c6, c2, 0
 350 
 351         mov     r0, #0x06
 352         mcr     p15, 0, r0, c2, c0, 0           @ region 1,2 d-cacheable
 353         mcr     p15, 0, r0, c2, c0, 1           @ region 1,2 i-cacheable
 354 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 355         mov     r0, #0x00                       @ disable whole write buffer
 356 #else
 357         mov     r0, #0x02                       @ region 1 write bufferred
 358 #endif
 359         mcr     p15, 0, r0, c3, c0, 0
 360 
 361 /*
 362  *  Access Permission Settings for future permission control by PU.
 363  *
 364  *                              priv.   user
 365  *      region 0 (whole)        rw      --      : b0001
 366  *      region 1 (RAM)          rw      rw      : b0011
 367  *      region 2 (FLASH)        rw      r-      : b0010
 368  *      region 3~7 (none)       --      --      : b0000
 369  */
 370         mov     r0, #0x00000031
 371         orr     r0, r0, #0x00000200
 372         mcr     p15, 0, r0, c5, c0, 2           @ set data access permission
 373         mcr     p15, 0, r0, c5, c0, 3           @ set inst. access permission
 374 
 375         mrc     p15, 0, r0, c1, c0              @ get control register
 376         orr     r0, r0, #0x00001000             @ I-cache
 377         orr     r0, r0, #0x00000005             @ MPU/D-cache
 378 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
 379         orr     r0, r0, #0x00004000             @ .1.. .... .... ....
 380 #endif
 381         ret     lr
 382 
 383         .size   __arm946_setup, . - __arm946_setup
 384 
 385         __INITDATA
 386 
 387         @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
 388         define_processor_functions arm946, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1
 389 
 390         .section ".rodata"
 391 
 392         string  cpu_arch_name, "armv5te"
 393         string  cpu_elf_name, "v5t"
 394         string  cpu_arm946_name, "ARM946E-S"
 395 
 396         .align
 397 
 398         .section ".proc.info.init", #alloc
 399         .type   __arm946_proc_info,#object
 400 __arm946_proc_info:
 401         .long   0x41009460
 402         .long   0xff00fff0
 403         .long   0
 404         .long   0
 405         initfn  __arm946_setup, __arm946_proc_info
 406         .long   cpu_arch_name
 407         .long   cpu_elf_name
 408         .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
 409         .long   cpu_arm946_name
 410         .long   arm946_processor_functions
 411         .long   0
 412         .long   0
 413         .long   arm946_cache_fns
 414         .size   __arm946_proc_info, . - __arm946_proc_info
 415 

/* [<][>][^][v][top][bottom][index][help] */