1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Coherency fabric: low level functions
5 * Copyright (C) 2012 Marvell
7 * Gregory CLEMENT <gregory.clement@free-electrons.com>
9 * This file implements the assembly function to add a CPU to the
10 * coherency fabric. This function is called by each of the secondary
11 * CPUs during their early boot in an SMP kernel, this why this
12 * function have to callable from assembly. It can also be called by a
13 * primary CPU from C code during its boot.
16 #include <linux/linkage.h>
17 #define ARMADA_XP_CFB_CTL_REG_OFFSET 0x0
18 #define ARMADA_XP_CFB_CFG_REG_OFFSET 0x4
20 #include <asm/assembler.h>
25 * Returns the coherency base address in r1 (r0 is untouched), or 0 if
26 * the coherency fabric is not enabled.
28 ENTRY(ll_get_coherency_base)
29 mrc p15, 0, r1, c1, c0, 0
30 tst r1, #CR_M @ Check MMU bit enabled
34 * MMU is disabled, use the physical address of the coherency
35 * base address, (or 0x0 if the coherency fabric is not mapped)
43 * MMU is enabled, use the virtual address of the coherency
46 ldr r1, =coherency_base
50 ENDPROC(ll_get_coherency_base)
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
60 ENTRY(ll_get_coherency_cpumask)
61 mrc p15, 0, r3, cr0, cr0, 5
67 ENDPROC(ll_get_coherency_cpumask)
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
78 ENTRY(ll_add_cpu_to_smp_group)
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.
87 bl ll_get_coherency_base
88 /* Bail out if the coherency is not enabled */
91 bl ll_get_coherency_cpumask
93 add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET
101 ENDPROC(ll_add_cpu_to_smp_group)
103 ENTRY(ll_enable_coherency)
105 * As r0 is not modified by ll_get_coherency_base() and
106 * ll_get_coherency_cpumask(), we use it to temporarly save lr
107 * and avoid it being modified by the branch and link
108 * calls. This function is used very early in the secondary
109 * CPU boot, and no stack is available at this point.
112 bl ll_get_coherency_base
113 /* Bail out if the coherency is not enabled */
116 bl ll_get_coherency_cpumask
118 add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
128 ENDPROC(ll_enable_coherency)
130 ENTRY(ll_disable_coherency)
132 * As r0 is not modified by ll_get_coherency_base() and
133 * ll_get_coherency_cpumask(), we use it to temporarly save lr
134 * and avoid it being modified by the branch and link
135 * calls. This function is used very early in the secondary
136 * CPU boot, and no stack is available at this point.
139 bl ll_get_coherency_base
140 /* Bail out if the coherency is not enabled */
143 bl ll_get_coherency_cpumask
145 add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
154 ENDPROC(ll_disable_coherency)
158 .long coherency_phys_base - .