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