Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arm64/include/asm/arch_gicv3.h
26481 views
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 __always_inline void gic_write_dir(u32 irq)
30
{
31
write_sysreg_s(irq, SYS_ICC_DIR_EL1);
32
isb();
33
}
34
35
static 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
*/
65
static 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
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
90
static inline void gic_write_ctlr(u32 val)
91
{
92
write_sysreg_s(val, SYS_ICC_CTLR_EL1);
93
isb();
94
}
95
96
static inline u32 gic_read_ctlr(void)
97
{
98
return read_sysreg_s(SYS_ICC_CTLR_EL1);
99
}
100
101
static inline void gic_write_grpen1(u32 val)
102
{
103
write_sysreg_s(val, SYS_ICC_IGRPEN1_EL1);
104
isb();
105
}
106
107
static inline void gic_write_sgi1r(u64 val)
108
{
109
write_sysreg_s(val, SYS_ICC_SGI1R_EL1);
110
}
111
112
static inline u32 gic_read_sre(void)
113
{
114
return read_sysreg_s(SYS_ICC_SRE_EL1);
115
}
116
117
static inline void gic_write_sre(u32 val)
118
{
119
write_sysreg_s(val, SYS_ICC_SRE_EL1);
120
isb();
121
}
122
123
static inline void gic_write_bpr1(u32 val)
124
{
125
write_sysreg_s(val, SYS_ICC_BPR1_EL1);
126
}
127
128
static inline u32 gic_read_pmr(void)
129
{
130
return read_sysreg_s(SYS_ICC_PMR_EL1);
131
}
132
133
static __always_inline void gic_write_pmr(u32 val)
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
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
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
{
178
gic_write_pmr(GIC_PRIO_IRQOFF);
179
}
180
181
static inline void gic_arch_enable_irqs(void)
182
{
183
asm volatile ("msr daifclr, #3" : : : "memory");
184
}
185
186
static inline bool gic_has_relaxed_pmr_sync(void)
187
{
188
return cpus_have_cap(ARM64_HAS_GIC_PRIO_RELAXED_SYNC);
189
}
190
191
#endif /* __ASSEMBLY__ */
192
#endif /* __ASM_ARCH_GICV3_H */
193
194