Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: add 32bit support to GICv3

Implement the system and memory-mapped register accesses in
asm/arch_gicv3.h for 32bit architectures.

This patch is a straightforward translation of the arm64 header. 64bit
accesses are done in two times and don't need atomicity: TYPER is
read-only, and the upper-word of IROUTER is always zero on 32bit
architectures.

Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

authored by

Jean-Philippe Brucker and committed by
Marc Zyngier
d5cd50d3 72c97126

+188
+188
arch/arm/include/asm/arch_gicv3.h
··· 1 + /* 2 + * arch/arm/include/asm/arch_gicv3.h 3 + * 4 + * Copyright (C) 2015 ARM Ltd. 5 + * 6 + * This program is free software: you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * You should have received a copy of the GNU General Public License 16 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 + */ 18 + #ifndef __ASM_ARCH_GICV3_H 19 + #define __ASM_ARCH_GICV3_H 20 + 21 + #ifndef __ASSEMBLY__ 22 + 23 + #include <linux/io.h> 24 + 25 + #define __ACCESS_CP15(CRn, Op1, CRm, Op2) p15, Op1, %0, CRn, CRm, Op2 26 + #define __ACCESS_CP15_64(Op1, CRm) p15, Op1, %Q0, %R0, CRm 27 + 28 + #define ICC_EOIR1 __ACCESS_CP15(c12, 0, c12, 1) 29 + #define ICC_DIR __ACCESS_CP15(c12, 0, c11, 1) 30 + #define ICC_IAR1 __ACCESS_CP15(c12, 0, c12, 0) 31 + #define ICC_SGI1R __ACCESS_CP15_64(0, c12) 32 + #define ICC_PMR __ACCESS_CP15(c4, 0, c6, 0) 33 + #define ICC_CTLR __ACCESS_CP15(c12, 0, c12, 4) 34 + #define ICC_SRE __ACCESS_CP15(c12, 0, c12, 5) 35 + #define ICC_IGRPEN1 __ACCESS_CP15(c12, 0, c12, 7) 36 + 37 + #define ICC_HSRE __ACCESS_CP15(c12, 4, c9, 5) 38 + 39 + #define ICH_VSEIR __ACCESS_CP15(c12, 4, c9, 4) 40 + #define ICH_HCR __ACCESS_CP15(c12, 4, c11, 0) 41 + #define ICH_VTR __ACCESS_CP15(c12, 4, c11, 1) 42 + #define ICH_MISR __ACCESS_CP15(c12, 4, c11, 2) 43 + #define ICH_EISR __ACCESS_CP15(c12, 4, c11, 3) 44 + #define ICH_ELSR __ACCESS_CP15(c12, 4, c11, 5) 45 + #define ICH_VMCR __ACCESS_CP15(c12, 4, c11, 7) 46 + 47 + #define __LR0(x) __ACCESS_CP15(c12, 4, c12, x) 48 + #define __LR8(x) __ACCESS_CP15(c12, 4, c13, x) 49 + 50 + #define ICH_LR0 __LR0(0) 51 + #define ICH_LR1 __LR0(1) 52 + #define ICH_LR2 __LR0(2) 53 + #define ICH_LR3 __LR0(3) 54 + #define ICH_LR4 __LR0(4) 55 + #define ICH_LR5 __LR0(5) 56 + #define ICH_LR6 __LR0(6) 57 + #define ICH_LR7 __LR0(7) 58 + #define ICH_LR8 __LR8(0) 59 + #define ICH_LR9 __LR8(1) 60 + #define ICH_LR10 __LR8(2) 61 + #define ICH_LR11 __LR8(3) 62 + #define ICH_LR12 __LR8(4) 63 + #define ICH_LR13 __LR8(5) 64 + #define ICH_LR14 __LR8(6) 65 + #define ICH_LR15 __LR8(7) 66 + 67 + /* LR top half */ 68 + #define __LRC0(x) __ACCESS_CP15(c12, 4, c14, x) 69 + #define __LRC8(x) __ACCESS_CP15(c12, 4, c15, x) 70 + 71 + #define ICH_LRC0 __LRC0(0) 72 + #define ICH_LRC1 __LRC0(1) 73 + #define ICH_LRC2 __LRC0(2) 74 + #define ICH_LRC3 __LRC0(3) 75 + #define ICH_LRC4 __LRC0(4) 76 + #define ICH_LRC5 __LRC0(5) 77 + #define ICH_LRC6 __LRC0(6) 78 + #define ICH_LRC7 __LRC0(7) 79 + #define ICH_LRC8 __LRC8(0) 80 + #define ICH_LRC9 __LRC8(1) 81 + #define ICH_LRC10 __LRC8(2) 82 + #define ICH_LRC11 __LRC8(3) 83 + #define ICH_LRC12 __LRC8(4) 84 + #define ICH_LRC13 __LRC8(5) 85 + #define ICH_LRC14 __LRC8(6) 86 + #define ICH_LRC15 __LRC8(7) 87 + 88 + #define __AP0Rx(x) __ACCESS_CP15(c12, 4, c8, x) 89 + #define ICH_AP0R0 __AP0Rx(0) 90 + #define ICH_AP0R1 __AP0Rx(1) 91 + #define ICH_AP0R2 __AP0Rx(2) 92 + #define ICH_AP0R3 __AP0Rx(3) 93 + 94 + #define __AP1Rx(x) __ACCESS_CP15(c12, 4, c9, x) 95 + #define ICH_AP1R0 __AP1Rx(0) 96 + #define ICH_AP1R1 __AP1Rx(1) 97 + #define ICH_AP1R2 __AP1Rx(2) 98 + #define ICH_AP1R3 __AP1Rx(3) 99 + 100 + /* Low-level accessors */ 101 + 102 + static inline void gic_write_eoir(u32 irq) 103 + { 104 + asm volatile("mcr " __stringify(ICC_EOIR1) : : "r" (irq)); 105 + isb(); 106 + } 107 + 108 + static inline void gic_write_dir(u32 val) 109 + { 110 + asm volatile("mcr " __stringify(ICC_DIR) : : "r" (val)); 111 + isb(); 112 + } 113 + 114 + static inline u32 gic_read_iar(void) 115 + { 116 + u32 irqstat; 117 + 118 + asm volatile("mrc " __stringify(ICC_IAR1) : "=r" (irqstat)); 119 + return irqstat; 120 + } 121 + 122 + static inline void gic_write_pmr(u32 val) 123 + { 124 + asm volatile("mcr " __stringify(ICC_PMR) : : "r" (val)); 125 + } 126 + 127 + static inline void gic_write_ctlr(u32 val) 128 + { 129 + asm volatile("mcr " __stringify(ICC_CTLR) : : "r" (val)); 130 + isb(); 131 + } 132 + 133 + static inline void gic_write_grpen1(u32 val) 134 + { 135 + asm volatile("mcr " __stringify(ICC_IGRPEN1) : : "r" (val)); 136 + isb(); 137 + } 138 + 139 + static inline void gic_write_sgi1r(u64 val) 140 + { 141 + asm volatile("mcrr " __stringify(ICC_SGI1R) : : "r" (val)); 142 + } 143 + 144 + static inline u32 gic_read_sre(void) 145 + { 146 + u32 val; 147 + 148 + asm volatile("mrc " __stringify(ICC_SRE) : "=r" (val)); 149 + return val; 150 + } 151 + 152 + static inline void gic_write_sre(u32 val) 153 + { 154 + asm volatile("mcr " __stringify(ICC_SRE) : : "r" (val)); 155 + isb(); 156 + } 157 + 158 + /* 159 + * Even in 32bit systems that use LPAE, there is no guarantee that the I/O 160 + * interface provides true 64bit atomic accesses, so using strd/ldrd doesn't 161 + * make much sense. 162 + * Moreover, 64bit I/O emulation is extremely difficult to implement on 163 + * AArch32, since the syndrome register doesn't provide any information for 164 + * them. 165 + * Consequently, the following IO helpers use 32bit accesses. 166 + * 167 + * There are only two registers that need 64bit accesses in this driver: 168 + * - GICD_IROUTERn, contain the affinity values associated to each interrupt. 169 + * The upper-word (aff3) will always be 0, so there is no need for a lock. 170 + * - GICR_TYPER is an ID register and doesn't need atomicity. 171 + */ 172 + static inline void gic_write_irouter(u64 val, volatile void __iomem *addr) 173 + { 174 + writel_relaxed((u32)val, addr); 175 + writel_relaxed((u32)(val >> 32), addr + 4); 176 + } 177 + 178 + static inline u64 gic_read_typer(const volatile void __iomem *addr) 179 + { 180 + u64 val; 181 + 182 + val = readl_relaxed(addr); 183 + val |= (u64)readl_relaxed(addr + 4) << 32; 184 + return val; 185 + } 186 + 187 + #endif /* !__ASSEMBLY__ */ 188 + #endif /* !__ASM_ARCH_GICV3_H */