Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / arch / arm / mm / proc-feroceon.S
index a02c171..f2e5884 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
 
 /*
@@ -59,6 +79,13 @@ ENTRY(cpu_feroceon_proc_fin)
        mov     ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
        msr     cpsr_c, ip
        bl      feroceon_flush_kern_cache_all
+
+#if defined(CONFIG_CACHE_FEROCEON_L2) && !defined(CONFIG_L2_CACHE_WRITETHROUGH)
+       mov     r0, #0
+       mcr     p15, 1, r0, c15, c9, 0          @ clean L2
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+#endif
+
        mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
        bic     r0, r0, #0x1000                 @ ...i............
        bic     r0, r0, #0x000e                 @ ............wca.
@@ -117,11 +144,19 @@ ENTRY(feroceon_flush_user_cache_all)
  */
 ENTRY(feroceon_flush_kern_cache_all)
        mov     r2, #VM_EXEC
-       mov     ip, #0
+
 __flush_whole_cache:
-1:     mrc     p15, 0, r15, c7, c14, 3         @ test,clean,invalidate
-       bne     1b
+       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
@@ -138,7 +173,6 @@ __flush_whole_cache:
  */
        .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
@@ -152,6 +186,7 @@ ENTRY(feroceon_flush_user_cache_range)
        cmp     r0, r1
        blo     1b
        tst     r2, #VM_EXEC
+       mov     ip, #0
        mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
        mov     pc, lr
 
@@ -209,6 +244,20 @@ ENTRY(feroceon_flush_kern_dcache_page)
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
+       .align  5
+ENTRY(feroceon_range_flush_kern_dcache_page)
+       mrs     r2, cpsr
+       add     r1, r0, #PAGE_SZ - CACHE_DLINESIZE      @ top addr is inclusive
+       orr     r3, r2, #PSR_I_BIT
+       msr     cpsr_c, r3                      @ disable interrupts
+       mcr     p15, 5, r0, c15, c15, 0         @ D clean/inv range start
+       mcr     p15, 5, r1, c15, c15, 1         @ D clean/inv range top
+       msr     cpsr_c, r2                      @ restore interrupts
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
 /*
  *     dma_inv_range(start, end)
  *
@@ -225,10 +274,10 @@ ENTRY(feroceon_flush_kern_dcache_page)
        .align  5
 ENTRY(feroceon_dma_inv_range)
        tst     r0, #CACHE_DLINESIZE - 1
+       bic     r0, 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
-       bic     r0, r0, #CACHE_DLINESIZE - 1
 1:     mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
@@ -236,6 +285,22 @@ ENTRY(feroceon_dma_inv_range)
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
+       .align  5
+ENTRY(feroceon_range_dma_inv_range)
+       mrs     r2, cpsr
+       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
+       cmp     r1, r0
+       subne   r1, r1, #1                      @ top address is inclusive
+       orr     r3, r2, #PSR_I_BIT
+       msr     cpsr_c, r3                      @ disable interrupts
+       mcr     p15, 5, r0, c15, c14, 0         @ D inv range start
+       mcr     p15, 5, r1, c15, c14, 1         @ D inv range top
+       msr     cpsr_c, r2                      @ restore interrupts
+       mov     pc, lr
+
 /*
  *     dma_clean_range(start, end)
  *
@@ -256,6 +321,19 @@ ENTRY(feroceon_dma_clean_range)
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
+       .align  5
+ENTRY(feroceon_range_dma_clean_range)
+       mrs     r2, cpsr
+       cmp     r1, r0
+       subne   r1, r1, #1                      @ top address is inclusive
+       orr     r3, r2, #PSR_I_BIT
+       msr     cpsr_c, r3                      @ disable interrupts
+       mcr     p15, 5, r0, c15, c13, 0         @ D clean range start
+       mcr     p15, 5, r1, c15, c13, 1         @ D clean range top
+       msr     cpsr_c, r2                      @ restore interrupts
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
 /*
  *     dma_flush_range(start, end)
  *
@@ -274,6 +352,19 @@ ENTRY(feroceon_dma_flush_range)
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
+       .align  5
+ENTRY(feroceon_range_dma_flush_range)
+       mrs     r2, cpsr
+       cmp     r1, r0
+       subne   r1, r1, #1                      @ top address is inclusive
+       orr     r3, r2, #PSR_I_BIT
+       msr     cpsr_c, r3                      @ disable interrupts
+       mcr     p15, 5, r0, c15, c15, 0         @ D clean/inv range start
+       mcr     p15, 5, r1, c15, c15, 1         @ D clean/inv range top
+       msr     cpsr_c, r2                      @ restore interrupts
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
 ENTRY(feroceon_cache_fns)
        .long   feroceon_flush_kern_cache_all
        .long   feroceon_flush_user_cache_all
@@ -285,12 +376,33 @@ ENTRY(feroceon_cache_fns)
        .long   feroceon_dma_clean_range
        .long   feroceon_dma_flush_range
 
+ENTRY(feroceon_range_cache_fns)
+       .long   feroceon_flush_kern_cache_all
+       .long   feroceon_flush_user_cache_all
+       .long   feroceon_flush_user_cache_range
+       .long   feroceon_coherent_kern_range
+       .long   feroceon_coherent_user_range
+       .long   feroceon_range_flush_kern_dcache_page
+       .long   feroceon_range_dma_inv_range
+       .long   feroceon_range_dma_clean_range
+       .long   feroceon_range_dma_flush_range
+
        .align  5
 ENTRY(cpu_feroceon_dcache_clean_area)
+#if defined(CONFIG_CACHE_FEROCEON_L2) && !defined(CONFIG_L2_CACHE_WRITETHROUGH)
+       mov     r2, r0
+       mov     r3, r1
+#endif
 1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        add     r0, r0, #CACHE_DLINESIZE
        subs    r1, r1, #CACHE_DLINESIZE
        bhi     1b
+#if defined(CONFIG_CACHE_FEROCEON_L2) && !defined(CONFIG_L2_CACHE_WRITETHROUGH)
+1:     mcr     p15, 1, r2, c15, c9, 1          @ clean L2 entry
+       add     r2, r2, #CACHE_DLINESIZE
+       subs    r3, r3, #CACHE_DLINESIZE
+       bhi     1b
+#endif
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
@@ -306,16 +418,25 @@ ENTRY(cpu_feroceon_dcache_clean_area)
        .align  5
 ENTRY(cpu_feroceon_switch_mm)
 #ifdef CONFIG_MMU
-       mov     ip, #0
-@ && 'Clean & Invalidate whole DCache'
-1:     mrc     p15, 0, r15, c7, c14, 3         @ test,clean,invalidate
-       bne     1b
-       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)
@@ -345,6 +466,9 @@ ENTRY(cpu_feroceon_set_pte_ext)
        str     r2, [r0]                        @ hardware version
        mov     r0, r0
        mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
+#if defined(CONFIG_CACHE_FEROCEON_L2) && !defined(CONFIG_L2_CACHE_WRITETHROUGH)
+       mcr     p15, 1, r0, c15, c9, 1          @ clean L2 entry
+#endif
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 #endif
        mov     pc, lr
@@ -369,14 +493,15 @@ __feroceon_setup:
        .size   __feroceon_setup, . - __feroceon_setup
 
        /*
-        *  R
-        * .RVI ZFRS BLDP WCAM
-        * .011 0001 ..11 0101
+        *      B
+        *  R   P
+        * .RVI UFRS BLDP WCAM
+        * .011 .001 ..11 0101
         *
         */
        .type   feroceon_crval, #object
 feroceon_crval:
-       crval   clear=0x00007f3f, mmuset=0x00003135, ucset=0x00001134
+       crval   clear=0x0000773f, mmuset=0x00003135, ucset=0x00001134
 
        __INITDATA
 
@@ -414,6 +539,21 @@ 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
+
+       .type   cpu_88fr571_name, #object
+cpu_88fr571_name:
+       .asciz  "Feroceon 88FR571-vd"
+       .size   cpu_88fr571_name, . - cpu_88fr571_name
+
+       .type   cpu_88fr131_name, #object
+cpu_88fr131_name:
+       .asciz  "Feroceon 88FR131"
+       .size   cpu_88fr131_name, . - cpu_88fr131_name
+
        .align
 
        .section ".proc.info.init", #alloc, #execinstr
@@ -421,15 +561,15 @@ cpu_feroceon_name:
 #ifdef CONFIG_CPU_FEROCEON_OLD_ID
        .type   __feroceon_old_id_proc_info,#object
 __feroceon_old_id_proc_info:
-       .long   0x41069260
-       .long   0xfffffff0
-       .long   PMD_TYPE_SECT | \
+       .long   0x41009260
+       .long   0xff00fff0
+       .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
@@ -445,17 +585,17 @@ __feroceon_old_id_proc_info:
        .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
@@ -463,9 +603,59 @@ __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   feroceon_user_fns
        .long   feroceon_cache_fns
-       .size   __feroceon_proc_info, . - __feroceon_proc_info
+       .size   __88fr531_proc_info, . - __88fr531_proc_info
+
+       .type   __88fr571_proc_info,#object
+__88fr571_proc_info:
+       .long   0x56155710
+       .long   0xfffffff0
+       .long   PMD_TYPE_SECT | \
+               PMD_SECT_BUFFERABLE | \
+               PMD_SECT_CACHEABLE | \
+               PMD_BIT4 | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ
+       .long   PMD_TYPE_SECT | \
+               PMD_BIT4 | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ
+       b       __feroceon_setup
+       .long   cpu_arch_name
+       .long   cpu_elf_name
+       .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+       .long   cpu_88fr571_name
+       .long   feroceon_processor_functions
+       .long   v4wbi_tlb_fns
+       .long   feroceon_user_fns
+       .long   feroceon_range_cache_fns
+       .size   __88fr571_proc_info, . - __88fr571_proc_info
+
+       .type   __88fr131_proc_info,#object
+__88fr131_proc_info:
+       .long   0x56251310
+       .long   0xfffffff0
+       .long   PMD_TYPE_SECT | \
+               PMD_SECT_BUFFERABLE | \
+               PMD_SECT_CACHEABLE | \
+               PMD_BIT4 | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ
+       .long   PMD_TYPE_SECT | \
+               PMD_BIT4 | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ
+       b       __feroceon_setup
+       .long   cpu_arch_name
+       .long   cpu_elf_name
+       .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+       .long   cpu_88fr131_name
+       .long   feroceon_processor_functions
+       .long   v4wbi_tlb_fns
+       .long   feroceon_user_fns
+       .long   feroceon_range_cache_fns
+       .size   __88fr131_proc_info, . - __88fr131_proc_info