Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Coherency fabric: low level functions
0004  *
0005  * Copyright (C) 2012 Marvell
0006  *
0007  * Gregory CLEMENT <gregory.clement@free-electrons.com>
0008  *
0009  * This file implements the assembly function to add a CPU to the
0010  * coherency fabric. This function is called by each of the secondary
0011  * CPUs during their early boot in an SMP kernel, this why this
0012  * function have to callable from assembly. It can also be called by a
0013  * primary CPU from C code during its boot.
0014  */
0015 
0016 #include <linux/linkage.h>
0017 #define ARMADA_XP_CFB_CTL_REG_OFFSET 0x0
0018 #define ARMADA_XP_CFB_CFG_REG_OFFSET 0x4
0019 
0020 #include <asm/assembler.h>
0021 #include <asm/cp15.h>
0022 
0023     .text
0024 /*
0025  * Returns the coherency base address in r1 (r0 is untouched), or 0 if
0026  * the coherency fabric is not enabled.
0027  */
0028 ENTRY(ll_get_coherency_base)
0029     mrc p15, 0, r1, c1, c0, 0
0030     tst r1, #CR_M @ Check MMU bit enabled
0031     bne 1f
0032 
0033     /*
0034      * MMU is disabled, use the physical address of the coherency
0035      * base address, (or 0x0 if the coherency fabric is not mapped)
0036      */
0037     adr r1, 3f
0038     ldr r3, [r1]
0039     ldr r1, [r1, r3]
0040     b   2f
0041 1:
0042     /*
0043      * MMU is enabled, use the virtual address of the coherency
0044      * base address.
0045      */
0046     ldr r1, =coherency_base
0047     ldr r1, [r1]
0048 2:
0049     ret lr
0050 ENDPROC(ll_get_coherency_base)
0051 
0052 /*
0053  * Returns the coherency CPU mask in r3 (r0 is untouched). This
0054  * coherency CPU mask can be used with the coherency fabric
0055  * configuration and control registers. Note that the mask is already
0056  * endian-swapped as appropriate so that the calling functions do not
0057  * have to care about endianness issues while accessing the coherency
0058  * fabric registers
0059  */
0060 ENTRY(ll_get_coherency_cpumask)
0061     mrc p15, 0, r3, cr0, cr0, 5
0062     and r3, r3, #15
0063     mov r2, #(1 << 24)
0064     lsl r3, r2, r3
0065 ARM_BE8(rev r3, r3)
0066     ret lr
0067 ENDPROC(ll_get_coherency_cpumask)
0068 
0069 /*
0070  * ll_add_cpu_to_smp_group(), ll_enable_coherency() and
0071  * ll_disable_coherency() use the strex/ldrex instructions while the
0072  * MMU can be disabled. The Armada XP SoC has an exclusive monitor
0073  * that tracks transactions to Device and/or SO memory and thanks to
0074  * that, exclusive transactions are functional even when the MMU is
0075  * disabled.
0076  */
0077 
0078 ENTRY(ll_add_cpu_to_smp_group)
0079     /*
0080      * As r0 is not modified by ll_get_coherency_base() and
0081      * ll_get_coherency_cpumask(), we use it to temporarly save lr
0082      * and avoid it being modified by the branch and link
0083      * calls. This function is used very early in the secondary
0084      * CPU boot, and no stack is available at this point.
0085      */
0086     mov     r0, lr
0087     bl  ll_get_coherency_base
0088     /* Bail out if the coherency is not enabled */
0089     cmp r1, #0
0090     reteq   r0
0091     bl  ll_get_coherency_cpumask
0092     mov     lr, r0
0093     add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET
0094 1:
0095     ldrex   r2, [r0]
0096     orr r2, r2, r3
0097     strex   r1, r2, [r0]
0098     cmp r1, #0
0099     bne 1b
0100     ret lr
0101 ENDPROC(ll_add_cpu_to_smp_group)
0102 
0103 ENTRY(ll_enable_coherency)
0104     /*
0105      * As r0 is not modified by ll_get_coherency_base() and
0106      * ll_get_coherency_cpumask(), we use it to temporarly save lr
0107      * and avoid it being modified by the branch and link
0108      * calls. This function is used very early in the secondary
0109      * CPU boot, and no stack is available at this point.
0110      */
0111     mov r0, lr
0112     bl  ll_get_coherency_base
0113     /* Bail out if the coherency is not enabled */
0114     cmp r1, #0
0115     reteq   r0
0116     bl  ll_get_coherency_cpumask
0117     mov lr, r0
0118     add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
0119 1:
0120     ldrex   r2, [r0]
0121     orr r2, r2, r3
0122     strex   r1, r2, [r0]
0123     cmp r1, #0
0124     bne 1b
0125     dsb
0126     mov r0, #0
0127     ret lr
0128 ENDPROC(ll_enable_coherency)
0129 
0130 ENTRY(ll_disable_coherency)
0131     /*
0132      * As r0 is not modified by ll_get_coherency_base() and
0133      * ll_get_coherency_cpumask(), we use it to temporarly save lr
0134      * and avoid it being modified by the branch and link
0135      * calls. This function is used very early in the secondary
0136      * CPU boot, and no stack is available at this point.
0137      */
0138     mov     r0, lr
0139     bl  ll_get_coherency_base
0140     /* Bail out if the coherency is not enabled */
0141     cmp r1, #0
0142     reteq   r0
0143     bl  ll_get_coherency_cpumask
0144     mov     lr, r0
0145     add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
0146 1:
0147     ldrex   r2, [r0]
0148     bic r2, r2, r3
0149     strex   r1, r2, [r0]
0150     cmp r1, #0
0151     bne 1b
0152     dsb
0153     ret lr
0154 ENDPROC(ll_disable_coherency)
0155 
0156     .align 2
0157 3:
0158     .long   coherency_phys_base - .