2 * Coherency fabric: low level functions
4 * Copyright (C) 2012 Marvell
6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
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.
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.
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>
28 * Returns the coherency base address in r1 (r0 is untouched), or 0 if
29 * the coherency fabric is not enabled.
31 ENTRY(ll_get_coherency_base)
32 mrc p15, 0, r1, c1, c0, 0
33 tst r1, #CR_M @ Check MMU bit enabled
37 * MMU is disabled, use the physical address of the coherency
38 * base address, (or 0x0 if the coherency fabric is not mapped)
46 * MMU is enabled, use the virtual address of the coherency
49 ldr r1, =coherency_base
53 ENDPROC(ll_get_coherency_base)
56 * Returns the coherency CPU mask in r3 (r0 is untouched). This
57 * coherency CPU mask can be used with the coherency fabric
58 * configuration and control registers. Note that the mask is already
59 * endian-swapped as appropriate so that the calling functions do not
60 * have to care about endianness issues while accessing the coherency
63 ENTRY(ll_get_coherency_cpumask)
64 mrc p15, 0, r3, cr0, cr0, 5
70 ENDPROC(ll_get_coherency_cpumask)
73 * ll_add_cpu_to_smp_group(), ll_enable_coherency() and
74 * ll_disable_coherency() use the strex/ldrex instructions while the
75 * MMU can be disabled. The Armada XP SoC has an exclusive monitor
76 * that tracks transactions to Device and/or SO memory and thanks to
77 * that, exclusive transactions are functional even when the MMU is
81 ENTRY(ll_add_cpu_to_smp_group)
83 * As r0 is not modified by ll_get_coherency_base() and
84 * ll_get_coherency_cpumask(), we use it to temporarly save lr
85 * and avoid it being modified by the branch and link
86 * calls. This function is used very early in the secondary
87 * CPU boot, and no stack is available at this point.
90 bl ll_get_coherency_base
91 /* Bail out if the coherency is not enabled */
94 bl ll_get_coherency_cpumask
96 add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET
104 ENDPROC(ll_add_cpu_to_smp_group)
106 ENTRY(ll_enable_coherency)
108 * As r0 is not modified by ll_get_coherency_base() and
109 * ll_get_coherency_cpumask(), we use it to temporarly save lr
110 * and avoid it being modified by the branch and link
111 * calls. This function is used very early in the secondary
112 * CPU boot, and no stack is available at this point.
115 bl ll_get_coherency_base
116 /* Bail out if the coherency is not enabled */
119 bl ll_get_coherency_cpumask
121 add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
131 ENDPROC(ll_enable_coherency)
133 ENTRY(ll_disable_coherency)
135 * As r0 is not modified by ll_get_coherency_base() and
136 * ll_get_coherency_cpumask(), we use it to temporarly save lr
137 * and avoid it being modified by the branch and link
138 * calls. This function is used very early in the secondary
139 * CPU boot, and no stack is available at this point.
142 bl ll_get_coherency_base
143 /* Bail out if the coherency is not enabled */
146 bl ll_get_coherency_cpumask
148 add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
157 ENDPROC(ll_disable_coherency)
161 .long coherency_phys_base - .