2  * linux/arch/arm/mm/proc-xsc3.S
 
   4  * Original Author: Matthew Gilbert
 
   5  * Current Maintainer: Lennert Buytenhek <buytenh@wantstofly.org>
 
   7  * Copyright 2004 (C) Intel Corp.
 
   8  * Copyright 2005 (C) MontaVista Software, Inc.
 
  10  * This program is free software; you can redistribute it and/or modify
 
  11  * it under the terms of the GNU General Public License version 2 as
 
  12  * published by the Free Software Foundation.
 
  14  * MMU functions for the Intel XScale3 Core (XSC3).  The XSC3 core is
 
  15  * an extension to Intel's original XScale core that adds the following
 
  18  * - ARMv6 Supersections
 
  19  * - Low Locality Reference pages (replaces mini-cache)
 
  22  * - Cache coherency if chipset supports it
 
  24  * Based on original XScale code by Nicolas Pitre.
 
  27 #include <linux/linkage.h>
 
  28 #include <linux/init.h>
 
  29 #include <asm/assembler.h>
 
  31 #include <asm/hardware.h>
 
  32 #include <asm/pgtable.h>
 
  33 #include <asm/pgtable-hwdef.h>
 
  35 #include <asm/ptrace.h>
 
  36 #include "proc-macros.S"
 
  39  * This is the maximum size of an area which will be flushed.  If the
 
  40  * area is larger than this, then we flush the whole cache.
 
  42 #define MAX_AREA_SIZE   32768
 
  45  * The cache line size of the L1 I, L1 D and unified L2 cache.
 
  47 #define CACHELINESIZE   32
 
  50  * The size of the L1 D cache.
 
  52 #define CACHESIZE       32768
 
  55  * Run with L2 enabled.
 
  57 #define L2_CACHE_ENABLE 1
 
  60  * This macro is used to wait for a CP15 write and is needed when we
 
  61  * have to ensure that the last operation to the coprocessor was
 
  62  * completed before continuing with operation.
 
  64         .macro  cpwait_ret, lr, rd
 
  65         mrc     p15, 0, \rd, c2, c0, 0          @ arbitrary read of cp15
 
  66         sub     pc, \lr, \rd, LSR #32           @ wait for completion and
 
  67                                                 @ flush instruction pipeline
 
  71  * This macro cleans and invalidates the entire L1 D cache.
 
  74         .macro  clean_d_cache rd, rs
 
  77 1:      mcr     p15, 0, \rd, c7, c14, 2         @ clean/invalidate L1 D line
 
  78         adds    \rd, \rd, #0x40000000
 
  87  * cpu_xsc3_proc_init()
 
  89  * Nothing too exciting at the moment
 
  91 ENTRY(cpu_xsc3_proc_init)
 
  97 ENTRY(cpu_xsc3_proc_fin)
 
  99         mov     r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
 
 101         bl      xsc3_flush_kern_cache_all       @ clean caches
 
 102         mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
 
 103         bic     r0, r0, #0x1800                 @ ...IZ...........
 
 104         bic     r0, r0, #0x0006                 @ .............CA.
 
 105         mcr     p15, 0, r0, c1, c0, 0           @ disable caches
 
 109  * cpu_xsc3_reset(loc)
 
 111  * Perform a soft reset of the system.  Put the CPU into the
 
 112  * same state as it would be if it had been reset, and branch
 
 113  * to what would be the reset vector.
 
 115  * loc: location to jump to for soft reset
 
 118 ENTRY(cpu_xsc3_reset)
 
 119         mov     r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
 
 120         msr     cpsr_c, r1                      @ reset CPSR
 
 121         mrc     p15, 0, r1, c1, c0, 0           @ ctrl register
 
 122         bic     r1, r1, #0x3900                 @ ..VIZ..S........
 
 123         bic     r1, r1, #0x0086                 @ ........B....CA.
 
 124         mcr     p15, 0, r1, c1, c0, 0           @ ctrl register
 
 125         mcr     p15, 0, ip, c7, c7, 0           @ invalidate L1 caches and BTB
 
 126         bic     r1, r1, #0x0001                 @ ...............M
 
 127         mcr     p15, 0, r1, c1, c0, 0           @ ctrl register
 
 128         @ CAUTION: MMU turned off from this point.  We count on the pipeline
 
 129         @ already containing those two last instructions to survive.
 
 130         mcr     p15, 0, ip, c8, c7, 0           @ invalidate I and D TLBs
 
 136  * Cause the processor to idle
 
 138  * For now we do nothing but go to idle mode for every case
 
 140  * XScale supports clock switching, but using idle mode support
 
 141  * allows external hardware to react to system state changes.
 
 145 ENTRY(cpu_xsc3_do_idle)
 
 147         mcr     p14, 0, r0, c7, c0, 0           @ go to idle
 
 150 /* ================================= CACHE ================================ */
 
 153  *      flush_user_cache_all()
 
 155  *      Invalidate all cache entries in a particular address
 
 158 ENTRY(xsc3_flush_user_cache_all)
 
 162  *      flush_kern_cache_all()
 
 164  *      Clean and invalidate the entire cache.
 
 166 ENTRY(xsc3_flush_kern_cache_all)
 
 172         mcrne   p15, 0, ip, c7, c5, 0           @ invalidate L1 I cache and BTB
 
 173         mcrne   p15, 0, ip, c7, c10, 4          @ data write barrier
 
 174         mcrne   p15, 0, ip, c7, c5, 4           @ prefetch flush
 
 178  *      flush_user_cache_range(start, end, vm_flags)
 
 180  *      Invalidate a range of cache entries in the specified
 
 183  *      - start - start address (may not be aligned)
 
 184  *      - end   - end address (exclusive, may not be aligned)
 
 185  *      - vma   - vma_area_struct describing address space
 
 188 ENTRY(xsc3_flush_user_cache_range)
 
 190         sub     r3, r1, r0                      @ calculate total size
 
 191         cmp     r3, #MAX_AREA_SIZE
 
 192         bhs     __flush_whole_cache
 
 195         mcrne   p15, 0, r0, c7, c5, 1           @ invalidate L1 I line
 
 196         mcr     p15, 0, r0, c7, c14, 1          @ clean/invalidate L1 D line
 
 197         add     r0, r0, #CACHELINESIZE
 
 201         mcrne   p15, 0, ip, c7, c5, 6           @ invalidate BTB
 
 202         mcrne   p15, 0, ip, c7, c10, 4          @ data write barrier
 
 203         mcrne   p15, 0, ip, c7, c5, 4           @ prefetch flush
 
 207  *      coherent_kern_range(start, end)
 
 209  *      Ensure coherency between the I cache and the D cache in the
 
 210  *      region described by start.  If you have non-snooping
 
 211  *      Harvard caches, you need to implement this function.
 
 213  *      - start  - virtual start address
 
 214  *      - end    - virtual end address
 
 216  *      Note: single I-cache line invalidation isn't used here since
 
 217  *      it also trashes the mini I-cache used by JTAG debuggers.
 
 219 ENTRY(xsc3_coherent_kern_range)
 
 221 ENTRY(xsc3_coherent_user_range)
 
 222         bic     r0, r0, #CACHELINESIZE - 1
 
 223 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
 
 224         add     r0, r0, #CACHELINESIZE
 
 228         mcr     p15, 0, r0, c7, c5, 0           @ invalidate L1 I cache and BTB
 
 229         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
 
 230         mcr     p15, 0, r0, c7, c5, 4           @ prefetch flush
 
 234  *      flush_kern_dcache_page(void *page)
 
 236  *      Ensure no D cache aliasing occurs, either with itself or
 
 239  *      - addr  - page aligned address
 
 241 ENTRY(xsc3_flush_kern_dcache_page)
 
 243 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean/invalidate L1 D line
 
 244         add     r0, r0, #CACHELINESIZE
 
 248         mcr     p15, 0, r0, c7, c5, 0           @ invalidate L1 I cache and BTB
 
 249         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
 
 250         mcr     p15, 0, r0, c7, c5, 4           @ prefetch flush
 
 254  *      dma_inv_range(start, end)
 
 256  *      Invalidate (discard) the specified virtual address range.
 
 257  *      May not write back any entries.  If 'start' or 'end'
 
 258  *      are not cache line aligned, those lines must be written
 
 261  *      - start  - virtual start address
 
 262  *      - end    - virtual end address
 
 264 ENTRY(xsc3_dma_inv_range)
 
 265         tst     r0, #CACHELINESIZE - 1
 
 266         bic     r0, r0, #CACHELINESIZE - 1
 
 267         mcrne   p15, 0, r0, c7, c10, 1          @ clean L1 D line
 
 268         mcrne   p15, 1, r0, c7, c11, 1          @ clean L2 line
 
 269         tst     r1, #CACHELINESIZE - 1
 
 270         mcrne   p15, 0, r1, c7, c10, 1          @ clean L1 D line
 
 271         mcrne   p15, 1, r1, c7, c11, 1          @ clean L2 line
 
 272 1:      mcr     p15, 0, r0, c7, c6, 1           @ invalidate L1 D line
 
 273         mcr     p15, 1, r0, c7, c7, 1           @ invalidate L2 line
 
 274         add     r0, r0, #CACHELINESIZE
 
 277         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
 
 281  *      dma_clean_range(start, end)
 
 283  *      Clean the specified virtual address range.
 
 285  *      - start  - virtual start address
 
 286  *      - end    - virtual end address
 
 288 ENTRY(xsc3_dma_clean_range)
 
 289         bic     r0, r0, #CACHELINESIZE - 1
 
 290 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
 
 291         mcr     p15, 1, r0, c7, c11, 1          @ clean L2 line
 
 292         add     r0, r0, #CACHELINESIZE
 
 295         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
 
 299  *      dma_flush_range(start, end)
 
 301  *      Clean and invalidate the specified virtual address range.
 
 303  *      - start  - virtual start address
 
 304  *      - end    - virtual end address
 
 306 ENTRY(xsc3_dma_flush_range)
 
 307         bic     r0, r0, #CACHELINESIZE - 1
 
 308 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean/invalidate L1 D line
 
 309         mcr     p15, 1, r0, c7, c11, 1          @ clean L2 line
 
 310         mcr     p15, 1, r0, c7, c7, 1           @ invalidate L2 line
 
 311         add     r0, r0, #CACHELINESIZE
 
 314         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
 
 317 ENTRY(xsc3_cache_fns)
 
 318         .long   xsc3_flush_kern_cache_all
 
 319         .long   xsc3_flush_user_cache_all
 
 320         .long   xsc3_flush_user_cache_range
 
 321         .long   xsc3_coherent_kern_range
 
 322         .long   xsc3_coherent_user_range
 
 323         .long   xsc3_flush_kern_dcache_page
 
 324         .long   xsc3_dma_inv_range
 
 325         .long   xsc3_dma_clean_range
 
 326         .long   xsc3_dma_flush_range
 
 328 ENTRY(cpu_xsc3_dcache_clean_area)
 
 329 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
 
 330         add     r0, r0, #CACHELINESIZE
 
 331         subs    r1, r1, #CACHELINESIZE
 
 335 /* =============================== PageTable ============================== */
 
 338  * cpu_xsc3_switch_mm(pgd)
 
 340  * Set the translation base pointer to be as described by pgd.
 
 342  * pgd: new page tables
 
 345 ENTRY(cpu_xsc3_switch_mm)
 
 347         mcr     p15, 0, ip, c7, c5, 0           @ invalidate L1 I cache and BTB
 
 348         mcr     p15, 0, ip, c7, c10, 4          @ data write barrier
 
 349         mcr     p15, 0, ip, c7, c5, 4           @ prefetch flush
 
 350 #ifdef L2_CACHE_ENABLE
 
 351         orr     r0, r0, #0x18                   @ cache the page table in L2
 
 353         mcr     p15, 0, r0, c2, c0, 0           @ load page table pointer
 
 354         mcr     p15, 0, ip, c8, c7, 0           @ invalidate I and D TLBs
 
 358  * cpu_xsc3_set_pte_ext(ptep, pte, ext)
 
 360  * Set a PTE and flush it out
 
 364 ENTRY(cpu_xsc3_set_pte_ext)
 
 365         str     r1, [r0], #-2048                @ linux version
 
 367         bic     r2, r1, #0xff0                  @ keep C, B bits
 
 368         orr     r2, r2, #PTE_TYPE_EXT           @ extended page
 
 369         tst     r1, #L_PTE_SHARED               @ shared?
 
 372         eor     r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
 
 374         tst     r3, #L_PTE_USER                 @ user?
 
 375         orrne   r2, r2, #PTE_EXT_AP_URO_SRW     @ yes -> user r/o, system r/w
 
 377         tst     r3, #L_PTE_WRITE | L_PTE_DIRTY  @ write and dirty?
 
 378         orreq   r2, r2, #PTE_EXT_AP_UNO_SRW     @ yes -> user n/a, system r/w
 
 379                                                 @ combined with user -> user r/w
 
 382         @ If it's cacheable, it needs to be in L2 also.
 
 383         eor     ip, r1, #L_PTE_CACHEABLE
 
 384         tst     ip, #L_PTE_CACHEABLE
 
 385         orreq   r2, r2, #PTE_EXT_TEX(0x5)
 
 388         tst     r3, #L_PTE_PRESENT | L_PTE_YOUNG        @ present and young?
 
 389         movne   r2, #0                          @ no -> fault
 
 391         str     r2, [r0]                        @ hardware version
 
 393         mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
 
 394         mcr     p15, 0, ip, c7, c10, 4          @ data write barrier
 
 403         .type   __xsc3_setup, #function
 
 405         mov     r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
 
 407         mcr     p15, 0, ip, c7, c7, 0           @ invalidate L1 caches and BTB
 
 408         mcr     p15, 0, ip, c7, c10, 4          @ data write barrier
 
 409         mcr     p15, 0, ip, c7, c5, 4           @ prefetch flush
 
 410         mcr     p15, 0, ip, c8, c7, 0           @ invalidate I and D TLBs
 
 412         orr     r4, r4, #0x18                   @ cache the page table in L2
 
 414         mcr     p15, 0, r4, c2, c0, 0           @ load page table pointer
 
 416         mov     r0, #0                          @ don't allow CP access
 
 417         mcr     p15, 0, r0, c15, c1, 0          @ write CP access register
 
 419         mrc     p15, 0, r0, c1, c0, 1           @ get auxiliary control reg
 
 420         and     r0, r0, #2                      @ preserve bit P bit setting
 
 422         orr     r0, r0, #(1 << 10)              @ enable L2 for LLR cache
 
 424         mcr     p15, 0, r0, c1, c0, 1           @ set auxiliary control reg
 
 428         mrc     p15, 0, r0, c1, c0, 0           @ get control register
 
 429         bic     r0, r0, r5                      @ ..V. ..R. .... ..A.
 
 430         orr     r0, r0, r6                      @ ..VI Z..S .... .C.M (mmu)
 
 431                                                 @ ...I Z..S .... .... (uc)
 
 433         orr     r0, r0, #0x04000000             @ L2 enable
 
 437         .size   __xsc3_setup, . - __xsc3_setup
 
 439         .type   xsc3_crval, #object
 
 441         crval   clear=0x04002202, mmuset=0x00003905, ucset=0x00001900
 
 446  * Purpose : Function pointers used to access above functions - all calls
 
 450         .type   xsc3_processor_functions, #object
 
 451 ENTRY(xsc3_processor_functions)
 
 452         .word   v5t_early_abort
 
 453         .word   cpu_xsc3_proc_init
 
 454         .word   cpu_xsc3_proc_fin
 
 456         .word   cpu_xsc3_do_idle
 
 457         .word   cpu_xsc3_dcache_clean_area
 
 458         .word   cpu_xsc3_switch_mm
 
 459         .word   cpu_xsc3_set_pte_ext
 
 460         .size   xsc3_processor_functions, . - xsc3_processor_functions
 
 464         .type   cpu_arch_name, #object
 
 467         .size   cpu_arch_name, . - cpu_arch_name
 
 469         .type   cpu_elf_name, #object
 
 472         .size   cpu_elf_name, . - cpu_elf_name
 
 474         .type   cpu_xsc3_name, #object
 
 476         .asciz  "XScale-V3 based processor"
 
 477         .size   cpu_xsc3_name, . - cpu_xsc3_name
 
 481         .section ".proc.info.init", #alloc, #execinstr
 
 483         .type   __xsc3_proc_info,#object
 
 487         .long   PMD_TYPE_SECT | \
 
 488                 PMD_SECT_BUFFERABLE | \
 
 489                 PMD_SECT_CACHEABLE | \
 
 490                 PMD_SECT_AP_WRITE | \
 
 492         .long   PMD_TYPE_SECT | \
 
 493                 PMD_SECT_AP_WRITE | \
 
 498         .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
 
 500         .long   xsc3_processor_functions
 
 502         .long   xsc3_mc_user_fns
 
 504         .size   __xsc3_proc_info, . - __xsc3_proc_info