linux/arch/arm/mm/proc-arm920.S
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/mm/proc-arm920.S: MMU functions for ARM920
   3 *
   4 *  Copyright (C) 1999,2000 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 arm920.
  25 *
  26 *  CONFIG_CPU_ARM920_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 * The size of one data cache line.
  40 */
  41#define CACHE_DLINESIZE 32
  42
  43/*
  44 * The number of data cache segments.
  45 */
  46#define CACHE_DSEGMENTS 8
  47
  48/*
  49 * The number of lines in a cache segment.
  50 */
  51#define CACHE_DENTRIES  64
  52
  53/*
  54 * This is the size at which it becomes more efficient to
  55 * clean the whole cache, rather than using the individual
  56 * cache line maintenance instructions.
  57 */
  58#define CACHE_DLIMIT    65536
  59
  60
  61        .text
  62/*
  63 * cpu_arm920_proc_init()
  64 */
  65ENTRY(cpu_arm920_proc_init)
  66        mov     pc, lr
  67
  68/*
  69 * cpu_arm920_proc_fin()
  70 */
  71ENTRY(cpu_arm920_proc_fin)
  72        mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
  73        bic     r0, r0, #0x1000                 @ ...i............
  74        bic     r0, r0, #0x000e                 @ ............wca.
  75        mcr     p15, 0, r0, c1, c0, 0           @ disable caches
  76        mov     pc, lr
  77
  78/*
  79 * cpu_arm920_reset(loc)
  80 *
  81 * Perform a soft reset of the system.  Put the CPU into the
  82 * same state as it would be if it had been reset, and branch
  83 * to what would be the reset vector.
  84 *
  85 * loc: location to jump to for soft reset
  86 */
  87        .align  5
  88        .pushsection    .idmap.text, "ax"
  89ENTRY(cpu_arm920_reset)
  90        mov     ip, #0
  91        mcr     p15, 0, ip, c7, c7, 0           @ invalidate I,D caches
  92        mcr     p15, 0, ip, c7, c10, 4          @ drain WB
  93#ifdef CONFIG_MMU
  94        mcr     p15, 0, ip, c8, c7, 0           @ invalidate I & D TLBs
  95#endif
  96        mrc     p15, 0, ip, c1, c0, 0           @ ctrl register
  97        bic     ip, ip, #0x000f                 @ ............wcam
  98        bic     ip, ip, #0x1100                 @ ...i...s........
  99        mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
 100        mov     pc, r0
 101ENDPROC(cpu_arm920_reset)
 102        .popsection
 103
 104/*
 105 * cpu_arm920_do_idle()
 106 */
 107        .align  5
 108ENTRY(cpu_arm920_do_idle)
 109        mcr     p15, 0, r0, c7, c0, 4           @ Wait for interrupt
 110        mov     pc, lr
 111
 112
 113#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 114
 115/*
 116 *      flush_icache_all()
 117 *
 118 *      Unconditionally clean and invalidate the entire icache.
 119 */
 120ENTRY(arm920_flush_icache_all)
 121        mov     r0, #0
 122        mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
 123        mov     pc, lr
 124ENDPROC(arm920_flush_icache_all)
 125
 126/*
 127 *      flush_user_cache_all()
 128 *
 129 *      Invalidate all cache entries in a particular address
 130 *      space.
 131 */
 132ENTRY(arm920_flush_user_cache_all)
 133        /* FALLTHROUGH */
 134
 135/*
 136 *      flush_kern_cache_all()
 137 *
 138 *      Clean and invalidate the entire cache.
 139 */
 140ENTRY(arm920_flush_kern_cache_all)
 141        mov     r2, #VM_EXEC
 142        mov     ip, #0
 143__flush_whole_cache:
 144        mov     r1, #(CACHE_DSEGMENTS - 1) << 5 @ 8 segments
 1451:      orr     r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
 1462:      mcr     p15, 0, r3, c7, c14, 2          @ clean+invalidate D index
 147        subs    r3, r3, #1 << 26
 148        bcs     2b                              @ entries 63 to 0
 149        subs    r1, r1, #1 << 5
 150        bcs     1b                              @ segments 7 to 0
 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 *      Invalidate a range of cache entries in the specified
 160 *      address space.
 161 *
 162 *      - start - start address (inclusive)
 163 *      - end   - end address (exclusive)
 164 *      - flags - vm_flags for address space
 165 */
 166ENTRY(arm920_flush_user_cache_range)
 167        mov     ip, #0
 168        sub     r3, r1, r0                      @ calculate total size
 169        cmp     r3, #CACHE_DLIMIT
 170        bhs     __flush_whole_cache
 171
 1721:      mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
 173        tst     r2, #VM_EXEC
 174        mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
 175        add     r0, r0, #CACHE_DLINESIZE
 176        cmp     r0, r1
 177        blo     1b
 178        tst     r2, #VM_EXEC
 179        mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
 180        mov     pc, lr
 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 */
 192ENTRY(arm920_coherent_kern_range)
 193        /* FALLTHROUGH */
 194
 195/*
 196 *      coherent_user_range(start, end)
 197 *
 198 *      Ensure coherency between the Icache and the Dcache in the
 199 *      region described by start, end.  If you have non-snooping
 200 *      Harvard caches, you need to implement this function.
 201 *
 202 *      - start - virtual start address
 203 *      - end   - virtual end address
 204 */
 205ENTRY(arm920_coherent_user_range)
 206        bic     r0, r0, #CACHE_DLINESIZE - 1
 2071:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
 208        mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
 209        add     r0, r0, #CACHE_DLINESIZE
 210        cmp     r0, r1
 211        blo     1b
 212        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 213        mov     r0, #0
 214        mov     pc, lr
 215
 216/*
 217 *      flush_kern_dcache_area(void *addr, size_t size)
 218 *
 219 *      Ensure no D cache aliasing occurs, either with itself or
 220 *      the I cache
 221 *
 222 *      - addr  - kernel address
 223 *      - size  - region size
 224 */
 225ENTRY(arm920_flush_kern_dcache_area)
 226        add     r1, r0, r1
 2271:      mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
 228        add     r0, r0, #CACHE_DLINESIZE
 229        cmp     r0, r1
 230        blo     1b
 231        mov     r0, #0
 232        mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
 233        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 234        mov     pc, lr
 235
 236/*
 237 *      dma_inv_range(start, end)
 238 *
 239 *      Invalidate (discard) the specified virtual address range.
 240 *      May not write back any entries.  If 'start' or 'end'
 241 *      are not cache line aligned, those lines must be written
 242 *      back.
 243 *
 244 *      - start - virtual start address
 245 *      - end   - virtual end address
 246 *
 247 * (same as v4wb)
 248 */
 249arm920_dma_inv_range:
 250        tst     r0, #CACHE_DLINESIZE - 1
 251        bic     r0, r0, #CACHE_DLINESIZE - 1
 252        mcrne   p15, 0, r0, c7, c10, 1          @ clean D entry
 253        tst     r1, #CACHE_DLINESIZE - 1
 254        mcrne   p15, 0, r1, c7, c10, 1          @ clean D entry
 2551:      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
 256        add     r0, r0, #CACHE_DLINESIZE
 257        cmp     r0, r1
 258        blo     1b
 259        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 260        mov     pc, lr
 261
 262/*
 263 *      dma_clean_range(start, end)
 264 *
 265 *      Clean the specified virtual address range.
 266 *
 267 *      - start - virtual start address
 268 *      - end   - virtual end address
 269 *
 270 * (same as v4wb)
 271 */
 272arm920_dma_clean_range:
 273        bic     r0, r0, #CACHE_DLINESIZE - 1
 2741:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
 275        add     r0, r0, #CACHE_DLINESIZE
 276        cmp     r0, r1
 277        blo     1b
 278        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 279        mov     pc, lr
 280
 281/*
 282 *      dma_flush_range(start, end)
 283 *
 284 *      Clean and invalidate the specified virtual address range.
 285 *
 286 *      - start - virtual start address
 287 *      - end   - virtual end address
 288 */
 289ENTRY(arm920_dma_flush_range)
 290        bic     r0, r0, #CACHE_DLINESIZE - 1
 2911:      mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
 292        add     r0, r0, #CACHE_DLINESIZE
 293        cmp     r0, r1
 294        blo     1b
 295        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 296        mov     pc, lr
 297
 298/*
 299 *      dma_map_area(start, size, dir)
 300 *      - start - kernel virtual start address
 301 *      - size  - size of region
 302 *      - dir   - DMA direction
 303 */
 304ENTRY(arm920_dma_map_area)
 305        add     r1, r1, r0
 306        cmp     r2, #DMA_TO_DEVICE
 307        beq     arm920_dma_clean_range
 308        bcs     arm920_dma_inv_range
 309        b       arm920_dma_flush_range
 310ENDPROC(arm920_dma_map_area)
 311
 312/*
 313 *      dma_unmap_area(start, size, dir)
 314 *      - start - kernel virtual start address
 315 *      - size  - size of region
 316 *      - dir   - DMA direction
 317 */
 318ENTRY(arm920_dma_unmap_area)
 319        mov     pc, lr
 320ENDPROC(arm920_dma_unmap_area)
 321
 322        .globl  arm920_flush_kern_cache_louis
 323        .equ    arm920_flush_kern_cache_louis, arm920_flush_kern_cache_all
 324
 325        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
 326        define_cache_functions arm920
 327#endif
 328
 329
 330ENTRY(cpu_arm920_dcache_clean_area)
 3311:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
 332        add     r0, r0, #CACHE_DLINESIZE
 333        subs    r1, r1, #CACHE_DLINESIZE
 334        bhi     1b
 335        mov     pc, lr
 336
 337/* =============================== PageTable ============================== */
 338
 339/*
 340 * cpu_arm920_switch_mm(pgd)
 341 *
 342 * Set the translation base pointer to be as described by pgd.
 343 *
 344 * pgd: new page tables
 345 */
 346        .align  5
 347ENTRY(cpu_arm920_switch_mm)
 348#ifdef CONFIG_MMU
 349        mov     ip, #0
 350#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 351        mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
 352#else
 353@ && 'Clean & Invalidate whole DCache'
 354@ && Re-written to use Index Ops.
 355@ && Uses registers r1, r3 and ip
 356
 357        mov     r1, #(CACHE_DSEGMENTS - 1) << 5 @ 8 segments
 3581:      orr     r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
 3592:      mcr     p15, 0, r3, c7, c14, 2          @ clean & invalidate D index
 360        subs    r3, r3, #1 << 26
 361        bcs     2b                              @ entries 63 to 0
 362        subs    r1, r1, #1 << 5
 363        bcs     1b                              @ segments 7 to 0
 364#endif
 365        mcr     p15, 0, ip, c7, c5, 0           @ invalidate I cache
 366        mcr     p15, 0, ip, c7, c10, 4          @ drain WB
 367        mcr     p15, 0, r0, c2, c0, 0           @ load page table pointer
 368        mcr     p15, 0, ip, c8, c7, 0           @ invalidate I & D TLBs
 369#endif
 370        mov     pc, lr
 371
 372/*
 373 * cpu_arm920_set_pte(ptep, pte, ext)
 374 *
 375 * Set a PTE and flush it out
 376 */
 377        .align  5
 378ENTRY(cpu_arm920_set_pte_ext)
 379#ifdef CONFIG_MMU
 380        armv3_set_pte_ext
 381        mov     r0, r0
 382        mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
 383        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 384#endif
 385        mov     pc, lr
 386
 387/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 388.globl  cpu_arm920_suspend_size
 389.equ    cpu_arm920_suspend_size, 4 * 3
 390#ifdef CONFIG_ARM_CPU_SUSPEND
 391ENTRY(cpu_arm920_do_suspend)
 392        stmfd   sp!, {r4 - r6, lr}
 393        mrc     p15, 0, r4, c13, c0, 0  @ PID
 394        mrc     p15, 0, r5, c3, c0, 0   @ Domain ID
 395        mrc     p15, 0, r6, c1, c0, 0   @ Control register
 396        stmia   r0, {r4 - r6}
 397        ldmfd   sp!, {r4 - r6, pc}
 398ENDPROC(cpu_arm920_do_suspend)
 399
 400ENTRY(cpu_arm920_do_resume)
 401        mov     ip, #0
 402        mcr     p15, 0, ip, c8, c7, 0   @ invalidate I+D TLBs
 403        mcr     p15, 0, ip, c7, c7, 0   @ invalidate I+D caches
 404        ldmia   r0, {r4 - r6}
 405        mcr     p15, 0, r4, c13, c0, 0  @ PID
 406        mcr     p15, 0, r5, c3, c0, 0   @ Domain ID
 407        mcr     p15, 0, r1, c2, c0, 0   @ TTB address
 408        mov     r0, r6                  @ control register
 409        b       cpu_resume_mmu
 410ENDPROC(cpu_arm920_do_resume)
 411#endif
 412
 413        __CPUINIT
 414
 415        .type   __arm920_setup, #function
 416__arm920_setup:
 417        mov     r0, #0
 418        mcr     p15, 0, r0, c7, c7              @ invalidate I,D caches on v4
 419        mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer on v4
 420#ifdef CONFIG_MMU
 421        mcr     p15, 0, r0, c8, c7              @ invalidate I,D TLBs on v4
 422#endif
 423        adr     r5, arm920_crval
 424        ldmia   r5, {r5, r6}
 425        mrc     p15, 0, r0, c1, c0              @ get control register v4
 426        bic     r0, r0, r5
 427        orr     r0, r0, r6
 428        mov     pc, lr
 429        .size   __arm920_setup, . - __arm920_setup
 430
 431        /*
 432         *  R
 433         * .RVI ZFRS BLDP WCAM
 434         * ..11 0001 ..11 0101
 435         * 
 436         */
 437        .type   arm920_crval, #object
 438arm920_crval:
 439        crval   clear=0x00003f3f, mmuset=0x00003135, ucset=0x00001130
 440
 441        __INITDATA
 442        @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
 443        define_processor_functions arm920, dabort=v4t_early_abort, pabort=legacy_pabort, suspend=1
 444
 445        .section ".rodata"
 446
 447        string  cpu_arch_name, "armv4t"
 448        string  cpu_elf_name, "v4"
 449        string  cpu_arm920_name, "ARM920T"
 450
 451        .align
 452
 453        .section ".proc.info.init", #alloc, #execinstr
 454
 455        .type   __arm920_proc_info,#object
 456__arm920_proc_info:
 457        .long   0x41009200
 458        .long   0xff00fff0
 459        .long   PMD_TYPE_SECT | \
 460                PMD_SECT_BUFFERABLE | \
 461                PMD_SECT_CACHEABLE | \
 462                PMD_BIT4 | \
 463                PMD_SECT_AP_WRITE | \
 464                PMD_SECT_AP_READ
 465        .long   PMD_TYPE_SECT | \
 466                PMD_BIT4 | \
 467                PMD_SECT_AP_WRITE | \
 468                PMD_SECT_AP_READ
 469        b       __arm920_setup
 470        .long   cpu_arch_name
 471        .long   cpu_elf_name
 472        .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
 473        .long   cpu_arm920_name
 474        .long   arm920_processor_functions
 475        .long   v4wbi_tlb_fns
 476        .long   v4wb_user_fns
 477#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 478        .long   arm920_cache_fns
 479#else
 480        .long   v4wt_cache_fns
 481#endif
 482        .size   __arm920_proc_info, . - __arm920_proc_info
 483