![]() |
|
|||
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 - .
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |