^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Coherency fabric: low level functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2012 Marvell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Gregory CLEMENT <gregory.clement@free-electrons.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This file implements the assembly function to add a CPU to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * coherency fabric. This function is called by each of the secondary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * CPUs during their early boot in an SMP kernel, this why this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * function have to callable from assembly. It can also be called by a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * primary CPU from C code during its boot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define ARMADA_XP_CFB_CTL_REG_OFFSET 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define ARMADA_XP_CFB_CFG_REG_OFFSET 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/assembler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/cp15.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) .text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Returns the coherency base address in r1 (r0 is untouched), or 0 if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * the coherency fabric is not enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) ENTRY(ll_get_coherency_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) mrc p15, 0, r1, c1, c0, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) tst r1, #CR_M @ Check MMU bit enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) bne 1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * MMU is disabled, use the physical address of the coherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * base address, (or 0x0 if the coherency fabric is not mapped)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) adr r1, 3f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) ldr r3, [r1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ldr r1, [r1, r3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) b 2f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * MMU is enabled, use the virtual address of the coherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * base address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ldr r1, =coherency_base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) ldr r1, [r1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ret lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ENDPROC(ll_get_coherency_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * Returns the coherency CPU mask in r3 (r0 is untouched). This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * coherency CPU mask can be used with the coherency fabric
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * configuration and control registers. Note that the mask is already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * endian-swapped as appropriate so that the calling functions do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * have to care about endianness issues while accessing the coherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * fabric registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ENTRY(ll_get_coherency_cpumask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) mrc p15, 0, r3, cr0, cr0, 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) and r3, r3, #15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) mov r2, #(1 << 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) lsl r3, r2, r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ARM_BE8(rev r3, r3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ret lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ENDPROC(ll_get_coherency_cpumask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * ll_add_cpu_to_smp_group(), ll_enable_coherency() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * ll_disable_coherency() use the strex/ldrex instructions while the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * MMU can be disabled. The Armada XP SoC has an exclusive monitor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * that tracks transactions to Device and/or SO memory and thanks to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * that, exclusive transactions are functional even when the MMU is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) ENTRY(ll_add_cpu_to_smp_group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * As r0 is not modified by ll_get_coherency_base() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * ll_get_coherency_cpumask(), we use it to temporarly save lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * and avoid it being modified by the branch and link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * calls. This function is used very early in the secondary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * CPU boot, and no stack is available at this point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) mov r0, lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) bl ll_get_coherency_base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* Bail out if the coherency is not enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) cmp r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) reteq r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) bl ll_get_coherency_cpumask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) mov lr, r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ldrex r2, [r0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) orr r2, r2, r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) strex r1, r2, [r0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) cmp r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) bne 1b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ret lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ENDPROC(ll_add_cpu_to_smp_group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ENTRY(ll_enable_coherency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * As r0 is not modified by ll_get_coherency_base() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * ll_get_coherency_cpumask(), we use it to temporarly save lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * and avoid it being modified by the branch and link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * calls. This function is used very early in the secondary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * CPU boot, and no stack is available at this point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) mov r0, lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) bl ll_get_coherency_base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* Bail out if the coherency is not enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) cmp r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) reteq r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) bl ll_get_coherency_cpumask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) mov lr, r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ldrex r2, [r0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) orr r2, r2, r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) strex r1, r2, [r0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) cmp r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) bne 1b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) dsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) mov r0, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ret lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ENDPROC(ll_enable_coherency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ENTRY(ll_disable_coherency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * As r0 is not modified by ll_get_coherency_base() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * ll_get_coherency_cpumask(), we use it to temporarly save lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * and avoid it being modified by the branch and link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * calls. This function is used very early in the secondary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * CPU boot, and no stack is available at this point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) mov r0, lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) bl ll_get_coherency_base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* Bail out if the coherency is not enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) cmp r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) reteq r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) bl ll_get_coherency_cpumask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) mov lr, r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ldrex r2, [r0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) bic r2, r2, r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) strex r1, r2, [r0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) cmp r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) bne 1b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) dsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ret lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ENDPROC(ll_disable_coherency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .align 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .long coherency_phys_base - .