Merge tag 'pm+acpi-4.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[linux/fpc-iii.git] / arch / arm / mach-mvebu / coherency_ll.S
blob8b2fbc8b6bc6ff46ab2fd38fbb335c5f74d4ec82
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  */
19 #include <linux/linkage.h>
20 #define ARMADA_XP_CFB_CTL_REG_OFFSET 0x0
21 #define ARMADA_XP_CFB_CFG_REG_OFFSET 0x4
23 #include <asm/assembler.h>
24 #include <asm/cp15.h>
26         .text
28  * Returns the coherency base address in r1 (r0 is untouched), or 0 if
29  * the coherency fabric is not enabled.
30  */
31 ENTRY(ll_get_coherency_base)
32         mrc     p15, 0, r1, c1, c0, 0
33         tst     r1, #CR_M @ Check MMU bit enabled
34         bne     1f
36         /*
37          * MMU is disabled, use the physical address of the coherency
38          * base address. However, if the coherency fabric isn't mapped
39          * (i.e its virtual address is zero), it means coherency is
40          * not enabled, so we return 0.
41          */
42         ldr     r1, =coherency_base
43         cmp     r1, #0
44         beq     2f
45         adr     r1, 3f
46         ldr     r3, [r1]
47         ldr     r1, [r1, r3]
48         b       2f
50         /*
51          * MMU is enabled, use the virtual address of the coherency
52          * base address.
53          */
54         ldr     r1, =coherency_base
55         ldr     r1, [r1]
57         ret     lr
58 ENDPROC(ll_get_coherency_base)
61  * Returns the coherency CPU mask in r3 (r0 is untouched). This
62  * coherency CPU mask can be used with the coherency fabric
63  * configuration and control registers. Note that the mask is already
64  * endian-swapped as appropriate so that the calling functions do not
65  * have to care about endianness issues while accessing the coherency
66  * fabric registers
67  */
68 ENTRY(ll_get_coherency_cpumask)
69         mrc     15, 0, r3, cr0, cr0, 5
70         and     r3, r3, #15
71         mov     r2, #(1 << 24)
72         lsl     r3, r2, r3
73 ARM_BE8(rev     r3, r3)
74         ret     lr
75 ENDPROC(ll_get_coherency_cpumask)
78  * ll_add_cpu_to_smp_group(), ll_enable_coherency() and
79  * ll_disable_coherency() use the strex/ldrex instructions while the
80  * MMU can be disabled. The Armada XP SoC has an exclusive monitor
81  * that tracks transactions to Device and/or SO memory and thanks to
82  * that, exclusive transactions are functional even when the MMU is
83  * disabled.
84  */
86 ENTRY(ll_add_cpu_to_smp_group)
87         /*
88          * As r0 is not modified by ll_get_coherency_base() and
89          * ll_get_coherency_cpumask(), we use it to temporarly save lr
90          * and avoid it being modified by the branch and link
91          * calls. This function is used very early in the secondary
92          * CPU boot, and no stack is available at this point.
93          */
94         mov     r0, lr
95         bl      ll_get_coherency_base
96         /* Bail out if the coherency is not enabled */
97         cmp     r1, #0
98         reteq   r0
99         bl      ll_get_coherency_cpumask
100         mov     lr, r0
101         add     r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET
103         ldrex   r2, [r0]
104         orr     r2, r2, r3
105         strex   r1, r2, [r0]
106         cmp     r1, #0
107         bne     1b
108         ret     lr
109 ENDPROC(ll_add_cpu_to_smp_group)
111 ENTRY(ll_enable_coherency)
112         /*
113          * As r0 is not modified by ll_get_coherency_base() and
114          * ll_get_coherency_cpumask(), we use it to temporarly save lr
115          * and avoid it being modified by the branch and link
116          * calls. This function is used very early in the secondary
117          * CPU boot, and no stack is available at this point.
118          */
119         mov r0, lr
120         bl      ll_get_coherency_base
121         /* Bail out if the coherency is not enabled */
122         cmp     r1, #0
123         reteq   r0
124         bl      ll_get_coherency_cpumask
125         mov lr, r0
126         add     r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
128         ldrex   r2, [r0]
129         orr     r2, r2, r3
130         strex   r1, r2, [r0]
131         cmp     r1, #0
132         bne     1b
133         dsb
134         mov     r0, #0
135         ret     lr
136 ENDPROC(ll_enable_coherency)
138 ENTRY(ll_disable_coherency)
139         /*
140          * As r0 is not modified by ll_get_coherency_base() and
141          * ll_get_coherency_cpumask(), we use it to temporarly save lr
142          * and avoid it being modified by the branch and link
143          * calls. This function is used very early in the secondary
144          * CPU boot, and no stack is available at this point.
145          */
146         mov     r0, lr
147         bl      ll_get_coherency_base
148         /* Bail out if the coherency is not enabled */
149         cmp     r1, #0
150         reteq   r0
151         bl      ll_get_coherency_cpumask
152         mov     lr, r0
153         add     r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
155         ldrex   r2, [r0]
156         bic     r2, r2, r3
157         strex   r1, r2, [r0]
158         cmp     r1, #0
159         bne     1b
160         dsb
161         ret     lr
162 ENDPROC(ll_disable_coherency)
164         .align 2
166         .long   coherency_phys_base - .