Commit | Line | Data |
---|---|---|
caab277b | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
7936e914 JPB |
2 | /* |
3 | * arch/arm64/include/asm/arch_gicv3.h | |
4 | * | |
5 | * Copyright (C) 2015 ARM Ltd. | |
7936e914 JPB |
6 | */ |
7 | #ifndef __ASM_ARCH_GICV3_H | |
8 | #define __ASM_ARCH_GICV3_H | |
9 | ||
10 | #include <asm/sysreg.h> | |
11 | ||
7936e914 JPB |
12 | #ifndef __ASSEMBLY__ |
13 | ||
b334481a | 14 | #include <linux/irqchip/arm-gic-common.h> |
7936e914 | 15 | #include <linux/stringify.h> |
8e31ed9c | 16 | #include <asm/barrier.h> |
328191c0 | 17 | #include <asm/cacheflush.h> |
7936e914 | 18 | |
0e9884fe MR |
19 | #define read_gicreg(r) read_sysreg_s(SYS_ ## r) |
20 | #define write_gicreg(v, r) write_sysreg_s(v, SYS_ ## r) | |
b5525ce8 | 21 | |
f6c86a41 JPB |
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 | */ | |
7936e914 | 28 | |
5c37f1ae | 29 | static __always_inline void gic_write_dir(u32 irq) |
7936e914 | 30 | { |
0e9884fe | 31 | write_sysreg_s(irq, SYS_ICC_DIR_EL1); |
7936e914 JPB |
32 | isb(); |
33 | } | |
34 | ||
35 | static inline u64 gic_read_iar_common(void) | |
36 | { | |
37 | u64 irqstat; | |
38 | ||
0e9884fe | 39 | irqstat = read_sysreg_s(SYS_ICC_IAR1_EL1); |
1a1ebd5f | 40 | dsb(sy); |
7936e914 JPB |
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). | |
24a147bc LC |
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. | |
7936e914 JPB |
64 | */ |
65 | static inline u64 gic_read_iar_cavium_thunderx(void) | |
66 | { | |
24a147bc | 67 | u64 irqstat, apr; |
7936e914 | 68 | |
24a147bc | 69 | apr = read_sysreg_s(SYS_ICC_AP1R0_EL1); |
016f98af | 70 | nops(8); |
0e9884fe | 71 | irqstat = read_sysreg_s(SYS_ICC_IAR1_EL1); |
016f98af | 72 | nops(4); |
7936e914 JPB |
73 | mb(); |
74 | ||
24a147bc LC |
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; | |
7936e914 JPB |
80 | } |
81 | ||
a98a5eac MR |
82 | static 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 | ||
f6c86a41 | 90 | static inline void gic_write_ctlr(u32 val) |
7936e914 | 91 | { |
0e9884fe | 92 | write_sysreg_s(val, SYS_ICC_CTLR_EL1); |
7936e914 JPB |
93 | isb(); |
94 | } | |
95 | ||
eda0d04a SD |
96 | static inline u32 gic_read_ctlr(void) |
97 | { | |
98 | return read_sysreg_s(SYS_ICC_CTLR_EL1); | |
99 | } | |
100 | ||
f6c86a41 | 101 | static inline void gic_write_grpen1(u32 val) |
7936e914 | 102 | { |
21bc5281 | 103 | write_sysreg_s(val, SYS_ICC_IGRPEN1_EL1); |
7936e914 JPB |
104 | isb(); |
105 | } | |
106 | ||
107 | static inline void gic_write_sgi1r(u64 val) | |
108 | { | |
0e9884fe | 109 | write_sysreg_s(val, SYS_ICC_SGI1R_EL1); |
7936e914 JPB |
110 | } |
111 | ||
f6c86a41 | 112 | static inline u32 gic_read_sre(void) |
7936e914 | 113 | { |
0e9884fe | 114 | return read_sysreg_s(SYS_ICC_SRE_EL1); |
7936e914 JPB |
115 | } |
116 | ||
f6c86a41 | 117 | static inline void gic_write_sre(u32 val) |
7936e914 | 118 | { |
0e9884fe | 119 | write_sysreg_s(val, SYS_ICC_SRE_EL1); |
7936e914 JPB |
120 | isb(); |
121 | } | |
122 | ||
91ef8442 DT |
123 | static inline void gic_write_bpr1(u32 val) |
124 | { | |
0e9884fe | 125 | write_sysreg_s(val, SYS_ICC_BPR1_EL1); |
91ef8442 DT |
126 | } |
127 | ||
e99da7c6 JT |
128 | static inline u32 gic_read_pmr(void) |
129 | { | |
130 | return read_sysreg_s(SYS_ICC_PMR_EL1); | |
131 | } | |
132 | ||
7733306b | 133 | static __always_inline void gic_write_pmr(u32 val) |
e99da7c6 JT |
134 | { |
135 | write_sysreg_s(val, SYS_ICC_PMR_EL1); | |
136 | } | |
137 | ||
138 | static inline u32 gic_read_rpr(void) | |
139 | { | |
140 | return read_sysreg_s(SYS_ICC_RPR_EL1); | |
141 | } | |
142 | ||
72c97126 JPB |
143 | #define gic_read_typer(c) readq_relaxed(c) |
144 | #define gic_write_irouter(v, c) writeq_relaxed(v, c) | |
f6a91da7 MZ |
145 | #define gic_read_lpir(c) readq_relaxed(c) |
146 | #define gic_write_lpir(v, c) writeq_relaxed(v, c) | |
72c97126 | 147 | |
814b1860 | 148 | #define gic_flush_dcache_to_poc(a,l) \ |
fade9c2c | 149 | dcache_clean_inval_poc((unsigned long)(a), (unsigned long)(a)+(l)) |
328191c0 | 150 | |
0968a619 VM |
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 | ||
5186a6cc ZY |
165 | #define gicr_write_vpropbaser(v, c) writeq_relaxed(v, c) |
166 | #define gicr_read_vpropbaser(c) readq_relaxed(c) | |
3ca63f36 | 167 | |
5186a6cc ZY |
168 | #define gicr_write_vpendbaser(v, c) writeq_relaxed(v, c) |
169 | #define gicr_read_vpendbaser(c) readq_relaxed(c) | |
3ca63f36 | 170 | |
3f1f3234 JT |
171 | static inline bool gic_prio_masking_enabled(void) |
172 | { | |
173 | return system_uses_irq_prio_masking(); | |
174 | } | |
175 | ||
176 | static inline void gic_pmr_mask_irqs(void) | |
177 | { | |
b334481a | 178 | gic_write_pmr(GIC_PRIO_IRQOFF); |
3f1f3234 JT |
179 | } |
180 | ||
181 | static inline void gic_arch_enable_irqs(void) | |
182 | { | |
f0098155 | 183 | asm volatile ("msr daifclr, #3" : : : "memory"); |
3f1f3234 JT |
184 | } |
185 | ||
8bf0a804 MR |
186 | static inline bool gic_has_relaxed_pmr_sync(void) |
187 | { | |
188 | return cpus_have_cap(ARM64_HAS_GIC_PRIO_RELAXED_SYNC); | |
189 | } | |
190 | ||
7936e914 JPB |
191 | #endif /* __ASSEMBLY__ */ |
192 | #endif /* __ASM_ARCH_GICV3_H */ |