]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/arm/mm/proc-feroceon.S
[ARM] Feroceon: speed up flushing of the entire cache
[linux-2.6-omap-h63xx.git] / arch / arm / mm / proc-feroceon.S
index fa0dc7e6f0ea6f473174ea877e54e2bb10c82d8d..00eadb5995c7146c293c888ce1546ec461a37780 100644 (file)
  */
 #define CACHE_DLINESIZE        32
 
+       .bss
+       .align 3
+__cache_params_loc:
+       .space  8
+
        .text
+__cache_params:
+       .word   __cache_params_loc
+
 /*
  * cpu_feroceon_proc_init()
  */
 ENTRY(cpu_feroceon_proc_init)
+       mrc     p15, 0, r0, c0, c0, 1           @ read cache type register
+       ldr     r1, __cache_params
+       mov     r2, #(16 << 5)
+       tst     r0, #(1 << 16)                  @ get way
+       mov     r0, r0, lsr #18                 @ get cache size order
+       movne   r3, #((4 - 1) << 30)            @ 4-way
+       and     r0, r0, #0xf
+       moveq   r3, #0                          @ 1-way
+       mov     r2, r2, lsl r0                  @ actual cache size
+       movne   r2, r2, lsr #2                  @ turned into # of sets
+       sub     r2, r2, #(1 << 5)
+       stmia   r1, {r2, r3}
        mov     pc, lr
 
 /*
@@ -93,7 +113,7 @@ ENTRY(cpu_feroceon_reset)
  *
  * Called with IRQs disabled
  */
-       .align  10
+       .align  5
 ENTRY(cpu_feroceon_do_idle)
        mov     r0, #0
        mcr     p15, 0, r0, c7, c10, 4          @ Drain write buffer
@@ -106,6 +126,7 @@ ENTRY(cpu_feroceon_do_idle)
  *     Clean and invalidate all cache entries in a particular
  *     address space.
  */
+       .align  5
 ENTRY(feroceon_flush_user_cache_all)
        /* FALLTHROUGH */
 
@@ -116,15 +137,19 @@ ENTRY(feroceon_flush_user_cache_all)
  */
 ENTRY(feroceon_flush_kern_cache_all)
        mov     r2, #VM_EXEC
-       mov     ip, #0
+
 __flush_whole_cache:
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-       mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
-#else
-1:     mrc     p15, 0, r15, c7, c14, 3         @ test,clean,invalidate
-       bne     1b
-#endif
+       ldr     r1, __cache_params
+       ldmia   r1, {r1, r3}
+1:     orr     ip, r1, r3
+2:     mcr     p15, 0, ip, c7, c14, 2          @ clean + invalidate D set/way
+       subs    ip, ip, #(1 << 30)              @ next way
+       bcs     2b
+       subs    r1, r1, #(1 << 5)               @ next set
+       bcs     1b
+
        tst     r2, #VM_EXEC
+       mov     ip, #0
        mcrne   p15, 0, ip, c7, c5, 0           @ invalidate I cache
        mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
        mov     pc, lr
@@ -139,30 +164,22 @@ __flush_whole_cache:
  *     - end   - end address (exclusive)
  *     - flags - vm_flags describing address space
  */
+       .align  5
 ENTRY(feroceon_flush_user_cache_range)
-       mov     ip, #0
        sub     r3, r1, r0                      @ calculate total size
        cmp     r3, #CACHE_DLIMIT
        bgt     __flush_whole_cache
 1:     tst     r2, #VM_EXEC
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-       mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
-       mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
-       add     r0, r0, #CACHE_DLINESIZE
-       mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
-       mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
-       add     r0, r0, #CACHE_DLINESIZE
-#else
        mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
        mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
        add     r0, r0, #CACHE_DLINESIZE
        mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
        mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
        add     r0, r0, #CACHE_DLINESIZE
-#endif
        cmp     r0, r1
        blo     1b
        tst     r2, #VM_EXEC
+       mov     ip, #0
        mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
        mov     pc, lr
 
@@ -176,6 +193,7 @@ ENTRY(feroceon_flush_user_cache_range)
  *     - start - virtual start address
  *     - end   - virtual end address
  */
+       .align  5
 ENTRY(feroceon_coherent_kern_range)
        /* FALLTHROUGH */
 
@@ -207,6 +225,7 @@ ENTRY(feroceon_coherent_user_range)
  *
  *     - addr  - page aligned address
  */
+       .align  5
 ENTRY(feroceon_flush_kern_dcache_page)
        add     r1, r0, #PAGE_SZ
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
@@ -231,13 +250,12 @@ ENTRY(feroceon_flush_kern_dcache_page)
  *
  * (same as v4wb)
  */
+       .align  5
 ENTRY(feroceon_dma_inv_range)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
        tst     r0, #CACHE_DLINESIZE - 1
        mcrne   p15, 0, r0, c7, c10, 1          @ clean D entry
        tst     r1, #CACHE_DLINESIZE - 1
        mcrne   p15, 0, r1, c7, c10, 1          @ clean D entry
-#endif
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:     mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
@@ -256,14 +274,13 @@ ENTRY(feroceon_dma_inv_range)
  *
  * (same as v4wb)
  */
+       .align  5
 ENTRY(feroceon_dma_clean_range)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
        blo     1b
-#endif
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
@@ -275,14 +292,10 @@ ENTRY(feroceon_dma_clean_range)
  *     - start - virtual start address
  *     - end   - virtual end address
  */
+       .align  5
 ENTRY(feroceon_dma_flush_range)
        bic     r0, r0, #CACHE_DLINESIZE - 1
-1:
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-       mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
-#else
-       mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
-#endif
+1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
        blo     1b
@@ -300,13 +313,12 @@ ENTRY(feroceon_cache_fns)
        .long   feroceon_dma_clean_range
        .long   feroceon_dma_flush_range
 
+       .align  5
 ENTRY(cpu_feroceon_dcache_clean_area)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        add     r0, r0, #CACHE_DLINESIZE
        subs    r1, r1, #CACHE_DLINESIZE
        bhi     1b
-#endif
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
@@ -322,20 +334,25 @@ ENTRY(cpu_feroceon_dcache_clean_area)
        .align  5
 ENTRY(cpu_feroceon_switch_mm)
 #ifdef CONFIG_MMU
-       mov     ip, #0
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-       mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
-#else
-@ && 'Clean & Invalidate whole DCache'
-1:     mrc     p15, 0, r15, c7, c14, 3         @ test,clean,invalidate
-       bne     1b
-#endif
-       mcr     p15, 0, ip, c7, c5, 0           @ invalidate I cache
-       mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       /*
+        * Note: we wish to call __flush_whole_cache but we need to preserve
+        * lr to do so.  The only way without touching main memory is to
+        * use r2 which is normally used to test the VM_EXEC flag, and
+        * compensate locally for the skipped ops if it is not set.
+        */
+       mov     r2, lr                          @ abuse r2 to preserve lr
+       bl      __flush_whole_cache
+       @ if r2 contains the VM_EXEC bit then the next 2 ops are done already
+       tst     r2, #VM_EXEC
+       mcreq   p15, 0, ip, c7, c5, 0           @ invalidate I cache
+       mcreq   p15, 0, ip, c7, c10, 4          @ drain WB
+
        mcr     p15, 0, r0, c2, c0, 0           @ load page table pointer
        mcr     p15, 0, ip, c8, c7, 0           @ invalidate I & D TLBs
-#endif
+       mov     pc, r2
+#else
        mov     pc, lr
+#endif
 
 /*
  * cpu_feroceon_set_pte_ext(ptep, pte, ext)
@@ -362,16 +379,9 @@ ENTRY(cpu_feroceon_set_pte_ext)
        tst     r1, #L_PTE_PRESENT | L_PTE_YOUNG        @ Present and Young?
        movne   r2, #0
 
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-       eor     r3, r2, #0x0a                   @ C & small page?
-       tst     r3, #0x0b
-       biceq   r2, r2, #4
-#endif
        str     r2, [r0]                        @ hardware version
        mov     r0, r0
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
        mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
-#endif
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 #endif
        mov     pc, lr
@@ -387,20 +397,11 @@ __feroceon_setup:
        mcr     p15, 0, r0, c8, c7              @ invalidate I,D TLBs on v4
 #endif
 
-
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-       mov     r0, #4                          @ disable write-back on caches explicitly
-       mcr     p15, 7, r0, c15, c0, 0
-#endif
-
        adr     r5, feroceon_crval
        ldmia   r5, {r5, r6}
        mrc     p15, 0, r0, c1, c0              @ get control register v4
        bic     r0, r0, r5
        orr     r0, r0, r6
-#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
-       orr     r0, r0, #0x4000                 @ .1.. .... .... ....
-#endif
        mov     pc, lr
        .size   __feroceon_setup, . - __feroceon_setup
 
@@ -423,6 +424,7 @@ feroceon_crval:
        .type   feroceon_processor_functions, #object
 feroceon_processor_functions:
        .word   v5t_early_abort
+       .word   pabort_noifar
        .word   cpu_feroceon_proc_init
        .word   cpu_feroceon_proc_fin
        .word   cpu_feroceon_reset
@@ -449,6 +451,11 @@ cpu_feroceon_name:
        .asciz  "Feroceon"
        .size   cpu_feroceon_name, . - cpu_feroceon_name
 
+       .type   cpu_88fr531_name, #object
+cpu_88fr531_name:
+       .asciz  "Feroceon 88FR531-vd"
+       .size   cpu_88fr531_name, . - cpu_88fr531_name
+
        .align
 
        .section ".proc.info.init", #alloc, #execinstr
@@ -458,13 +465,13 @@ cpu_feroceon_name:
 __feroceon_old_id_proc_info:
        .long   0x41069260
        .long   0xfffffff0
-       .long   PMD_TYPE_SECT | \
+       .long   PMD_TYPE_SECT | \
                PMD_SECT_BUFFERABLE | \
                PMD_SECT_CACHEABLE | \
                PMD_BIT4 | \
                PMD_SECT_AP_WRITE | \
                PMD_SECT_AP_READ
-       .long   PMD_TYPE_SECT | \
+       .long   PMD_TYPE_SECT | \
                PMD_BIT4 | \
                PMD_SECT_AP_WRITE | \
                PMD_SECT_AP_READ
@@ -475,22 +482,22 @@ __feroceon_old_id_proc_info:
        .long   cpu_feroceon_name
        .long   feroceon_processor_functions
        .long   v4wbi_tlb_fns
-       .long   v4wb_user_fns
+       .long   feroceon_user_fns
        .long   feroceon_cache_fns
        .size   __feroceon_old_id_proc_info, . - __feroceon_old_id_proc_info
 #endif
 
-       .type   __feroceon_proc_info,#object
-__feroceon_proc_info:
+       .type   __88fr531_proc_info,#object
+__88fr531_proc_info:
        .long   0x56055310
        .long   0xfffffff0
-       .long   PMD_TYPE_SECT | \
+       .long   PMD_TYPE_SECT | \
                PMD_SECT_BUFFERABLE | \
                PMD_SECT_CACHEABLE | \
                PMD_BIT4 | \
                PMD_SECT_AP_WRITE | \
                PMD_SECT_AP_READ
-       .long   PMD_TYPE_SECT | \
+       .long   PMD_TYPE_SECT | \
                PMD_BIT4 | \
                PMD_SECT_AP_WRITE | \
                PMD_SECT_AP_READ
@@ -498,9 +505,9 @@ __feroceon_proc_info:
        .long   cpu_arch_name
        .long   cpu_elf_name
        .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-       .long   cpu_feroceon_name
+       .long   cpu_88fr531_name
        .long   feroceon_processor_functions
        .long   v4wbi_tlb_fns
-       .long   v4wb_user_fns
+       .long   feroceon_user_fns
        .long   feroceon_cache_fns
-       .size   __feroceon_proc_info, . - __feroceon_proc_info
+       .size   __88fr531_proc_info, . - __88fr531_proc_info