]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - arch/arm/mach-mvebu/coherency_ll.S
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
[mirror_ubuntu-zesty-kernel.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 /*
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
35
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
49 1:
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]
56 2:
57 ret lr
58 ENDPROC(ll_get_coherency_base)
59
60 /*
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)
76
77 /*
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 */
85
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
102 1:
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)
110
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
127 1:
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)
137
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
154 1:
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)
163
164 .align 2
165 3:
166 .long coherency_phys_base - .