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 */ 31ENTRY(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, (or 0x0 if the coherency fabric is not mapped) 39 */ 40 ldr_l r1, coherency_phys_base 41 b 2f 421: 43 /* 44 * MMU is enabled, use the virtual address of the coherency 45 * base address. 46 */ 47 ldr r1, =coherency_base 48 ldr r1, [r1] 492: 50 ret lr 51ENDPROC(ll_get_coherency_base) 52 53/* 54 * Returns the coherency CPU mask in r3 (r0 is untouched). This 55 * coherency CPU mask can be used with the coherency fabric 56 * configuration and control registers. Note that the mask is already 57 * endian-swapped as appropriate so that the calling functions do not 58 * have to care about endianness issues while accessing the coherency 59 * fabric registers 60 */ 61ENTRY(ll_get_coherency_cpumask) 62 mrc p15, 0, r3, cr0, cr0, 5 63 and r3, r3, #15 64 mov r2, #(1 << 24) 65 lsl r3, r2, r3 66ARM_BE8(rev r3, r3) 67 ret lr 68ENDPROC(ll_get_coherency_cpumask) 69 70/* 71 * ll_add_cpu_to_smp_group(), ll_enable_coherency() and 72 * ll_disable_coherency() use the strex/ldrex instructions while the 73 * MMU can be disabled. The Armada XP SoC has an exclusive monitor 74 * that tracks transactions to Device and/or SO memory and thanks to 75 * that, exclusive transactions are functional even when the MMU is 76 * disabled. 77 */ 78 79ENTRY(ll_add_cpu_to_smp_group) 80 /* 81 * As r0 is not modified by ll_get_coherency_base() and 82 * ll_get_coherency_cpumask(), we use it to temporarly save lr 83 * and avoid it being modified by the branch and link 84 * calls. This function is used very early in the secondary 85 * CPU boot, and no stack is available at this point. 86 */ 87 mov r0, lr 88 bl ll_get_coherency_base 89 /* Bail out if the coherency is not enabled */ 90 cmp r1, #0 91 reteq r0 92 bl ll_get_coherency_cpumask 93 mov lr, r0 94 add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET 951: 96 ldrex r2, [r0] 97 orr r2, r2, r3 98 strex r1, r2, [r0] 99 cmp r1, #0 100 bne 1b 101 ret lr 102ENDPROC(ll_add_cpu_to_smp_group) 103 104ENTRY(ll_enable_coherency) 105 /* 106 * As r0 is not modified by ll_get_coherency_base() and 107 * ll_get_coherency_cpumask(), we use it to temporarly save lr 108 * and avoid it being modified by the branch and link 109 * calls. This function is used very early in the secondary 110 * CPU boot, and no stack is available at this point. 111 */ 112 mov r0, lr 113 bl ll_get_coherency_base 114 /* Bail out if the coherency is not enabled */ 115 cmp r1, #0 116 reteq r0 117 bl ll_get_coherency_cpumask 118 mov lr, r0 119 add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET 1201: 121 ldrex r2, [r0] 122 orr r2, r2, r3 123 strex r1, r2, [r0] 124 cmp r1, #0 125 bne 1b 126 dsb 127 mov r0, #0 128 ret lr 129ENDPROC(ll_enable_coherency) 130 131ENTRY(ll_disable_coherency) 132 /* 133 * As r0 is not modified by ll_get_coherency_base() and 134 * ll_get_coherency_cpumask(), we use it to temporarly save lr 135 * and avoid it being modified by the branch and link 136 * calls. This function is used very early in the secondary 137 * CPU boot, and no stack is available at this point. 138 */ 139 mov r0, lr 140 bl ll_get_coherency_base 141 /* Bail out if the coherency is not enabled */ 142 cmp r1, #0 143 reteq r0 144 bl ll_get_coherency_cpumask 145 mov lr, r0 146 add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET 1471: 148 ldrex r2, [r0] 149 bic r2, r2, r3 150 strex r1, r2, [r0] 151 cmp r1, #0 152 bne 1b 153 dsb 154 ret lr 155ENDPROC(ll_disable_coherency) 156