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