ARM: mvebu: Split low level functions to manipulate HW coherency
authorGregory CLEMENT <gregory.clement@free-electrons.com>
Mon, 14 Apr 2014 15:10:08 +0000 (17:10 +0200)
committerJason Cooper <jason@lakedaemon.net>
Thu, 8 May 2014 16:18:54 +0000 (16:18 +0000)
Actually enabling coherency and adding a CPU on a SMP group are two
different operations which can be done separately. This patch splits
this in two functions.

Moreover as they use common pattern, this patch also creates local low
level functions (ll_get_coherency_base and ll_get_cpuid) to be used by
the exposed functions (ll_add_cpu_to_smp_group and
ll_enable_coherency)

Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Link: https://lkml.kernel.org/r/1397488214-20685-6-git-send-email-gregory.clement@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
arch/arm/mach-mvebu/coherency.c
arch/arm/mach-mvebu/coherency_ll.S
arch/arm/mach-mvebu/headsmp.S

index 944372a18ed6a0c58ce3fe8d75aee059ebe346f0..9d5ccd372712ffa0e16e50e17585468a86ab2e09 100644 (file)
@@ -60,8 +60,9 @@ static struct of_device_id of_coherency_table[] = {
        { /* end of list */ },
 };
 
-/* Function defined in coherency_ll.S */
-int ll_set_cpu_coherent(void);
+/* Functions defined in coherency_ll.S */
+int ll_enable_coherency(void);
+void ll_add_cpu_to_smp_group(void);
 
 int set_cpu_coherent(void)
 {
@@ -71,7 +72,8 @@ int set_cpu_coherent(void)
                return 1;
        }
 
-       return ll_set_cpu_coherent();
+       ll_add_cpu_to_smp_group();
+       return ll_enable_coherency();
 }
 
 /*
index 98a0b73f909b179e4b376698ba71d8c2f84c1373..f2e2e8677c4b05a0d800f8e9dff69172aac63a71 100644 (file)
 #include <asm/cp15.h>
 
        .text
-
-ENTRY(ll_set_cpu_coherent)
+/* Returns with the coherency address in r1 (r0 is untouched)*/
+ENTRY(ll_get_coherency_base)
        mrc     p15, 0, r1, c1, c0, 0
        tst     r1, #CR_M @ Check MMU bit enabled
        bne     1f
 
-       /* use physical address of the coherency register*/
-       adr     r0, 3f
-       ldr     r3, [r0]
-       ldr     r0, [r0, r3]
+       /* use physical address of the coherency register */
+       adr     r1, 3f
+       ldr     r3, [r1]
+       ldr     r1, [r1, r3]
        b       2f
 1:
-       /* use virtual address of the coherency register*/
-       ldr     r0, =coherency_base
-       ldr     r0, [r0]
+       /* use virtual address of the coherency register */
+       ldr     r1, =coherency_base
+       ldr     r1, [r1]
 2:
-       /* Create bit by cpu index */
-       mrc     15, 0, r1, cr0, cr0, 5
-       and     r1, r1, #15
+       mov     pc, lr
+ENDPROC(ll_get_coherency_base)
+
+/* Returns with the CPU ID in r3 (r0 is untouched)*/
+ENTRY(ll_get_cpuid)
+       mrc     15, 0, r3, cr0, cr0, 5
+       and     r3, r3, #15
        mov     r2, #(1 << 24)
-       lsl     r1, r2, r1
+       lsl     r3, r2, r3
 ARM_BE8(rev    r1, r1)
+       mov     pc, lr
+ENDPROC(ll_get_cpuid)
 
-       /* Add CPU to SMP group - Atomic */
-       add     r3, r0, #ARMADA_XP_CFB_CTL_REG_OFFSET
-1:
-       ldrex   r2, [r3]
-       orr     r2, r2, r1
-       strex   r0, r2, [r3]
-       cmp     r0, #0
-       bne 1b
+/* ll_add_cpu_to_smp_group, ll_enable_coherency and
+ * ll_disable_coherency use strex/ldrex whereas MMU can be off. The
+ * Armada XP SoC has an exclusive monitor that can track transactions
+ * to Device and/or SO and as such also when MMU is disabled the
+ * exclusive transactions will be functional
+ */
 
-       /* Enable coherency on CPU - Atomic */
-       add     r3, r3, #ARMADA_XP_CFB_CFG_REG_OFFSET
+ENTRY(ll_add_cpu_to_smp_group)
+       /*
+        * r0 being untouched in ll_get_coherency_base and
+        * ll_get_cpuid, we can use it to save lr modifing it with the
+        * following bl
+        */
+       mov r0, lr
+       bl      ll_get_coherency_base
+       bl      ll_get_cpuid
+       mov lr, r0
+       add     r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET
 1:
-       ldrex   r2, [r3]
-       orr     r2, r2, r1
-       strex   r0, r2, [r3]
-       cmp     r0, #0
-       bne 1b
+       ldrex   r2, [r0]
+       orr     r2, r2, r3
+       strex   r1, r2, [r0]
+       cmp     r1, #0
+       bne     1b
+       mov     pc, lr
+ENDPROC(ll_add_cpu_to_smp_group)
 
+ENTRY(ll_enable_coherency)
+       /*
+        * r0 being untouched in ll_get_coherency_base and
+        * ll_get_cpuid, we can use it to save lr modifing it with the
+        * following bl
+        */
+       mov r0, lr
+       bl      ll_get_coherency_base
+       bl      ll_get_cpuid
+       mov lr, r0
+       add     r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
+1:
+       ldrex   r2, [r0]
+       orr     r2, r2, r3
+       strex   r1, r2, [r0]
+       cmp     r1, #0
+       bne     1b
        dsb
-
        mov     r0, #0
        mov     pc, lr
-ENDPROC(ll_set_cpu_coherent)
+ENDPROC(ll_enable_coherency)
+
 
        .align 2
 3:
index cf7abe6554f721dc32c6634b09a1ae7d4861f2d7..2c4032e368badaa94d5ff60b7a6361b42d7f04dd 100644 (file)
 ENTRY(armada_xp_secondary_startup)
  ARM_BE8(setend        be )                    @ go BE8 if entered LE
 
-       /* Add CPU to coherency fabric */
-       bl      ll_set_cpu_coherent
+       bl      ll_add_cpu_to_smp_group
+
+       bl      ll_enable_coherency
+
        b       secondary_startup
 
 ENDPROC(armada_xp_secondary_startup)