1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * arch/arm64/include/asm/arch_gicv3.h 4 * 5 * Copyright (C) 2015 ARM Ltd. 6 */ 7 #ifndef __ASM_ARCH_GICV3_H 8 #define __ASM_ARCH_GICV3_H 9 10 #include <asm/sysreg.h> 11 12 #ifndef __ASSEMBLY__ 13 14 #include <linux/irqchip/arm-gic-common.h> 15 #include <linux/stringify.h> 16 #include <asm/barrier.h> 17 #include <asm/cacheflush.h> 18 19 #define read_gicreg(r) read_sysreg_s(SYS_ ## r) 20 #define write_gicreg(v, r) write_sysreg_s(v, SYS_ ## r) 21 22 /* 23 * Low-level accessors 24 * 25 * These system registers are 32 bits, but we make sure that the compiler 26 * sets the GP register's most significant bits to 0 with an explicit cast. 27 */ 28 29 static inline void gic_write_eoir(u32 irq) 30 { 31 write_sysreg_s(irq, SYS_ICC_EOIR1_EL1); 32 isb(); 33 } 34 35 static __always_inline void gic_write_dir(u32 irq) 36 { 37 write_sysreg_s(irq, SYS_ICC_DIR_EL1); 38 isb(); 39 } 40 41 static inline u64 gic_read_iar_common(void) 42 { 43 u64 irqstat; 44 45 irqstat = read_sysreg_s(SYS_ICC_IAR1_EL1); 46 dsb(sy); 47 return irqstat; 48 } 49 50 /* 51 * Cavium ThunderX erratum 23154 52 * 53 * The gicv3 of ThunderX requires a modified version for reading the 54 * IAR status to ensure data synchronization (access to icc_iar1_el1 55 * is not sync'ed before and after). 56 * 57 * Erratum 38545 58 * 59 * When a IAR register read races with a GIC interrupt RELEASE event, 60 * GIC-CPU interface could wrongly return a valid INTID to the CPU 61 * for an interrupt that is already released(non activated) instead of 0x3ff. 62 * 63 * To workaround this, return a valid interrupt ID only if there is a change 64 * in the active priority list after the IAR read. 65 * 66 * Common function used for both the workarounds since, 67 * 1. On Thunderx 88xx 1.x both erratas are applicable. 68 * 2. Having extra nops doesn't add any side effects for Silicons where 69 * erratum 23154 is not applicable. 70 */ 71 static inline u64 gic_read_iar_cavium_thunderx(void) 72 { 73 u64 irqstat, apr; 74 75 apr = read_sysreg_s(SYS_ICC_AP1R0_EL1); 76 nops(8); 77 irqstat = read_sysreg_s(SYS_ICC_IAR1_EL1); 78 nops(4); 79 mb(); 80 81 /* Max priority groups implemented is only 32 */ 82 if (likely(apr != read_sysreg_s(SYS_ICC_AP1R0_EL1))) 83 return irqstat; 84 85 return 0x3ff; 86 } 87 88 static inline void gic_write_ctlr(u32 val) 89 { 90 write_sysreg_s(val, SYS_ICC_CTLR_EL1); 91 isb(); 92 } 93 94 static inline u32 gic_read_ctlr(void) 95 { 96 return read_sysreg_s(SYS_ICC_CTLR_EL1); 97 } 98 99 static inline void gic_write_grpen1(u32 val) 100 { 101 write_sysreg_s(val, SYS_ICC_IGRPEN1_EL1); 102 isb(); 103 } 104 105 static inline void gic_write_sgi1r(u64 val) 106 { 107 write_sysreg_s(val, SYS_ICC_SGI1R_EL1); 108 } 109 110 static inline u32 gic_read_sre(void) 111 { 112 return read_sysreg_s(SYS_ICC_SRE_EL1); 113 } 114 115 static inline void gic_write_sre(u32 val) 116 { 117 write_sysreg_s(val, SYS_ICC_SRE_EL1); 118 isb(); 119 } 120 121 static inline void gic_write_bpr1(u32 val) 122 { 123 write_sysreg_s(val, SYS_ICC_BPR1_EL1); 124 } 125 126 static inline u32 gic_read_pmr(void) 127 { 128 return read_sysreg_s(SYS_ICC_PMR_EL1); 129 } 130 131 static __always_inline void gic_write_pmr(u32 val) 132 { 133 write_sysreg_s(val, SYS_ICC_PMR_EL1); 134 } 135 136 static inline u32 gic_read_rpr(void) 137 { 138 return read_sysreg_s(SYS_ICC_RPR_EL1); 139 } 140 141 #define gic_read_typer(c) readq_relaxed(c) 142 #define gic_write_irouter(v, c) writeq_relaxed(v, c) 143 #define gic_read_lpir(c) readq_relaxed(c) 144 #define gic_write_lpir(v, c) writeq_relaxed(v, c) 145 146 #define gic_flush_dcache_to_poc(a,l) \ 147 dcache_clean_inval_poc((unsigned long)(a), (unsigned long)(a)+(l)) 148 149 #define gits_read_baser(c) readq_relaxed(c) 150 #define gits_write_baser(v, c) writeq_relaxed(v, c) 151 152 #define gits_read_cbaser(c) readq_relaxed(c) 153 #define gits_write_cbaser(v, c) writeq_relaxed(v, c) 154 155 #define gits_write_cwriter(v, c) writeq_relaxed(v, c) 156 157 #define gicr_read_propbaser(c) readq_relaxed(c) 158 #define gicr_write_propbaser(v, c) writeq_relaxed(v, c) 159 160 #define gicr_write_pendbaser(v, c) writeq_relaxed(v, c) 161 #define gicr_read_pendbaser(c) readq_relaxed(c) 162 163 #define gicr_write_vpropbaser(v, c) writeq_relaxed(v, c) 164 #define gicr_read_vpropbaser(c) readq_relaxed(c) 165 166 #define gicr_write_vpendbaser(v, c) writeq_relaxed(v, c) 167 #define gicr_read_vpendbaser(c) readq_relaxed(c) 168 169 static inline bool gic_prio_masking_enabled(void) 170 { 171 return system_uses_irq_prio_masking(); 172 } 173 174 static inline void gic_pmr_mask_irqs(void) 175 { 176 BUILD_BUG_ON(GICD_INT_DEF_PRI < (__GIC_PRIO_IRQOFF | 177 GIC_PRIO_PSR_I_SET)); 178 BUILD_BUG_ON(GICD_INT_DEF_PRI >= GIC_PRIO_IRQON); 179 /* 180 * Need to make sure IRQON allows IRQs when SCR_EL3.FIQ is cleared 181 * and non-secure PMR accesses are not subject to the shifts that 182 * are applied to IRQ priorities 183 */ 184 BUILD_BUG_ON((0x80 | (GICD_INT_DEF_PRI >> 1)) >= GIC_PRIO_IRQON); 185 /* 186 * Same situation as above, but now we make sure that we can mask 187 * regular interrupts. 188 */ 189 BUILD_BUG_ON((0x80 | (GICD_INT_DEF_PRI >> 1)) < (__GIC_PRIO_IRQOFF_NS | 190 GIC_PRIO_PSR_I_SET)); 191 gic_write_pmr(GIC_PRIO_IRQOFF); 192 } 193 194 static inline void gic_arch_enable_irqs(void) 195 { 196 asm volatile ("msr daifclr, #3" : : : "memory"); 197 } 198 199 #endif /* __ASSEMBLY__ */ 200 #endif /* __ASM_ARCH_GICV3_H */ 201