root/arch/arm/mach-mvebu/coherency_ll.S

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

/* [<][>][^][v][top][bottom][index][help] */