ARM: shmobile: armadillo800eva: Build DTS for multiplatform
[cascardo/linux.git] / arch / arm / mach-mvebu / coherency_ll.S
1 /*
2  * Coherency fabric: low level functions
3  *
4  * Copyright (C) 2012 Marvell
5  *
6  * Gregory CLEMENT <gregory.clement@free-electrons.com>
7  *
8  * This file is licensed under the terms of the GNU General Public
9  * License version 2.  This program is licensed "as is" without any
10  * warranty of any kind, whether express or implied.
11  *
12  * This file implements the assembly function to add a CPU to the
13  * coherency fabric. This function is called by each of the secondary
14  * CPUs during their early boot in an SMP kernel, this why this
15  * function have to callable from assembly. It can also be called by a
16  * primary CPU from C code during its boot.
17  */
18
19 #include <linux/linkage.h>
20 #define ARMADA_XP_CFB_CTL_REG_OFFSET 0x0
21 #define ARMADA_XP_CFB_CFG_REG_OFFSET 0x4
22
23 #include <asm/assembler.h>
24 #include <asm/cp15.h>
25
26         .text
27 /* Returns the coherency base address in r1 (r0 is untouched) */
28 ENTRY(ll_get_coherency_base)
29         mrc     p15, 0, r1, c1, c0, 0
30         tst     r1, #CR_M @ Check MMU bit enabled
31         bne     1f
32
33         /*
34          * MMU is disabled, use the physical address of the coherency
35          * base address.
36          */
37         adr     r1, 3f
38         ldr     r3, [r1]
39         ldr     r1, [r1, r3]
40         b       2f
41 1:
42         /*
43          * MMU is enabled, use the virtual address of the coherency
44          * base address.
45          */
46         ldr     r1, =coherency_base
47         ldr     r1, [r1]
48 2:
49         ret     lr
50 ENDPROC(ll_get_coherency_base)
51
52 /*
53  * Returns the coherency CPU mask in r3 (r0 is untouched). This
54  * coherency CPU mask can be used with the coherency fabric
55  * configuration and control registers. Note that the mask is already
56  * endian-swapped as appropriate so that the calling functions do not
57  * have to care about endianness issues while accessing the coherency
58  * fabric registers
59  */
60 ENTRY(ll_get_coherency_cpumask)
61         mrc     15, 0, r3, cr0, cr0, 5
62         and     r3, r3, #15
63         mov     r2, #(1 << 24)
64         lsl     r3, r2, r3
65 ARM_BE8(rev     r3, r3)
66         ret     lr
67 ENDPROC(ll_get_coherency_cpumask)
68
69 /*
70  * ll_add_cpu_to_smp_group(), ll_enable_coherency() and
71  * ll_disable_coherency() use the strex/ldrex instructions while the
72  * MMU can be disabled. The Armada XP SoC has an exclusive monitor
73  * that tracks transactions to Device and/or SO memory and thanks to
74  * that, exclusive transactions are functional even when the MMU is
75  * disabled.
76  */
77
78 ENTRY(ll_add_cpu_to_smp_group)
79         /*
80          * As r0 is not modified by ll_get_coherency_base() and
81          * ll_get_coherency_cpumask(), we use it to temporarly save lr
82          * and avoid it being modified by the branch and link
83          * calls. This function is used very early in the secondary
84          * CPU boot, and no stack is available at this point.
85          */
86         mov     r0, lr
87         bl      ll_get_coherency_base
88         bl      ll_get_coherency_cpumask
89         mov     lr, r0
90         add     r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET
91 1:
92         ldrex   r2, [r0]
93         orr     r2, r2, r3
94         strex   r1, r2, [r0]
95         cmp     r1, #0
96         bne     1b
97         ret     lr
98 ENDPROC(ll_add_cpu_to_smp_group)
99
100 ENTRY(ll_enable_coherency)
101         /*
102          * As r0 is not modified by ll_get_coherency_base() and
103          * ll_get_coherency_cpumask(), we use it to temporarly save lr
104          * and avoid it being modified by the branch and link
105          * calls. This function is used very early in the secondary
106          * CPU boot, and no stack is available at this point.
107          */
108         mov r0, lr
109         bl      ll_get_coherency_base
110         bl      ll_get_coherency_cpumask
111         mov lr, r0
112         add     r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
113 1:
114         ldrex   r2, [r0]
115         orr     r2, r2, r3
116         strex   r1, r2, [r0]
117         cmp     r1, #0
118         bne     1b
119         dsb
120         mov     r0, #0
121         ret     lr
122 ENDPROC(ll_enable_coherency)
123
124 ENTRY(ll_disable_coherency)
125         /*
126          * As r0 is not modified by ll_get_coherency_base() and
127          * ll_get_coherency_cpumask(), we use it to temporarly save lr
128          * and avoid it being modified by the branch and link
129          * calls. This function is used very early in the secondary
130          * CPU boot, and no stack is available at this point.
131          */
132         mov     r0, lr
133         bl      ll_get_coherency_base
134         bl      ll_get_coherency_cpumask
135         mov     lr, r0
136         add     r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
137 1:
138         ldrex   r2, [r0]
139         bic     r2, r2, r3
140         strex   r1, r2, [r0]
141         cmp     r1, #0
142         bne     1b
143         dsb
144         ret     lr
145 ENDPROC(ll_disable_coherency)
146
147         .align 2
148 3:
149         .long   coherency_phys_base - .