Commit | Line | Data |
---|---|---|
009f1315 GC |
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 | ||
bca028e7 | 23 | #include <asm/assembler.h> |
ccd6a131 | 24 | #include <asm/cp15.h> |
bca028e7 | 25 | |
009f1315 | 26 | .text |
30cdef97 TP |
27 | /* |
28 | * Returns the coherency base address in r1 (r0 is untouched), or 0 if | |
29 | * the coherency fabric is not enabled. | |
30 | */ | |
2e8a5942 | 31 | ENTRY(ll_get_coherency_base) |
ccd6a131 GC |
32 | mrc p15, 0, r1, c1, c0, 0 |
33 | tst r1, #CR_M @ Check MMU bit enabled | |
34 | bne 1f | |
35 | ||
4dd1b7fa TP |
36 | /* |
37 | * MMU is disabled, use the physical address of the coherency | |
30cdef97 TP |
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. | |
4dd1b7fa | 41 | */ |
30cdef97 TP |
42 | ldr r1, =coherency_base |
43 | cmp r1, #0 | |
44 | beq 2f | |
2e8a5942 GC |
45 | adr r1, 3f |
46 | ldr r3, [r1] | |
47 | ldr r1, [r1, r3] | |
ccd6a131 GC |
48 | b 2f |
49 | 1: | |
4dd1b7fa TP |
50 | /* |
51 | * MMU is enabled, use the virtual address of the coherency | |
52 | * base address. | |
53 | */ | |
2e8a5942 GC |
54 | ldr r1, =coherency_base |
55 | ldr r1, [r1] | |
ccd6a131 | 56 | 2: |
6ebbf2ce | 57 | ret lr |
2e8a5942 GC |
58 | ENDPROC(ll_get_coherency_base) |
59 | ||
07ae144b TP |
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) | |
2e8a5942 GC |
69 | mrc 15, 0, r3, cr0, cr0, 5 |
70 | and r3, r3, #15 | |
b41375f7 | 71 | mov r2, #(1 << 24) |
2e8a5942 | 72 | lsl r3, r2, r3 |
4fbe6393 | 73 | ARM_BE8(rev r3, r3) |
6ebbf2ce | 74 | ret lr |
07ae144b | 75 | ENDPROC(ll_get_coherency_cpumask) |
009f1315 | 76 | |
4dd1b7fa TP |
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. | |
2e8a5942 | 84 | */ |
009f1315 | 85 | |
2e8a5942 GC |
86 | ENTRY(ll_add_cpu_to_smp_group) |
87 | /* | |
4dd1b7fa | 88 | * As r0 is not modified by ll_get_coherency_base() and |
07ae144b TP |
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. | |
2e8a5942 | 93 | */ |
90ba76f6 | 94 | mov r0, lr |
2e8a5942 | 95 | bl ll_get_coherency_base |
30cdef97 TP |
96 | /* Bail out if the coherency is not enabled */ |
97 | cmp r1, #0 | |
98 | reteq r0 | |
07ae144b | 99 | bl ll_get_coherency_cpumask |
90ba76f6 | 100 | mov lr, r0 |
2e8a5942 | 101 | add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET |
b60b61d4 | 102 | 1: |
2e8a5942 GC |
103 | ldrex r2, [r0] |
104 | orr r2, r2, r3 | |
105 | strex r1, r2, [r0] | |
106 | cmp r1, #0 | |
107 | bne 1b | |
6ebbf2ce | 108 | ret lr |
2e8a5942 | 109 | ENDPROC(ll_add_cpu_to_smp_group) |
009f1315 | 110 | |
2e8a5942 GC |
111 | ENTRY(ll_enable_coherency) |
112 | /* | |
4dd1b7fa | 113 | * As r0 is not modified by ll_get_coherency_base() and |
07ae144b TP |
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. | |
2e8a5942 GC |
118 | */ |
119 | mov r0, lr | |
120 | bl ll_get_coherency_base | |
30cdef97 TP |
121 | /* Bail out if the coherency is not enabled */ |
122 | cmp r1, #0 | |
123 | reteq r0 | |
07ae144b | 124 | bl ll_get_coherency_cpumask |
2e8a5942 GC |
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 | |
009f1315 | 133 | dsb |
009f1315 | 134 | mov r0, #0 |
6ebbf2ce | 135 | ret lr |
2e8a5942 GC |
136 | ENDPROC(ll_enable_coherency) |
137 | ||
1a6bfbc3 GC |
138 | ENTRY(ll_disable_coherency) |
139 | /* | |
4dd1b7fa | 140 | * As r0 is not modified by ll_get_coherency_base() and |
07ae144b TP |
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. | |
1a6bfbc3 | 145 | */ |
90ba76f6 | 146 | mov r0, lr |
1a6bfbc3 | 147 | bl ll_get_coherency_base |
30cdef97 TP |
148 | /* Bail out if the coherency is not enabled */ |
149 | cmp r1, #0 | |
150 | reteq r0 | |
07ae144b | 151 | bl ll_get_coherency_cpumask |
90ba76f6 | 152 | mov lr, r0 |
1a6bfbc3 GC |
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 | |
6ebbf2ce | 161 | ret lr |
1a6bfbc3 | 162 | ENDPROC(ll_disable_coherency) |
ccd6a131 GC |
163 | |
164 | .align 2 | |
165 | 3: | |
166 | .long coherency_phys_base - . |