1 /*
2 * Copyright (c) 2012-2019 LK Trusty Authors. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23 #pragma once
24
25 #include <stdint.h>
26 #include <platform/gic.h>
27 #include <reg.h>
28
29 #if ARCH_ARM
30 #include <arch/arm.h>
31 #endif
32 #if ARCH_ARM64
33 #include <arch/arm64.h>
34 #endif
35
36 #ifdef ARCH_ARM
37 /*
38 * AArch32 does not have 64 bit mmio support, but the gic spec allows 32 bit
39 * upper and lower access to _most_ 64 bit gic registers (not GICR_VSGIPENDR,
40 * GICR_VSGIR or GITS_SGIR).
41 */
42 /* TODO: add mmio_read32 when needed */
mmio_write64(volatile uint64_t * ptr64,uint64_t val)43 static inline void mmio_write64(volatile uint64_t *ptr64, uint64_t val) {
44 volatile uint32_t *ptr = (volatile uint32_t *)ptr64;
45 mmio_write32(ptr, (uint32_t)val);
46 mmio_write32(ptr + 1, val >> 32);
47 }
48 #endif
49
50 struct arm_gic {
51 vaddr_t gicc_vaddr;
52 size_t gicc_size;
53 vaddr_t gicd_vaddr;
54 size_t gicd_size;
55 vaddr_t gicr_vaddr;
56 size_t gicr_size;
57 };
58
59 #define NUM_ARM_GICS 1
60
61 extern struct arm_gic arm_gics[NUM_ARM_GICS];
62
63 #if GIC_VERSION > 2
64
65 #if WITH_LIB_SM
66 #define ARM_GIC_USE_DOORBELL_NS_IRQ 1
67 #define ARM_GIC_DOORBELL_IRQ 13
68 #endif
69
70 /* GICv3/v4 */
71
72 #define GICV3_IRQ_GROUP_GRP0S 0
73 #define GICV3_IRQ_GROUP_GRP1NS 1
74 #define GICV3_IRQ_GROUP_GRP1S 2
75
76 #ifndef ARM_GIC_SELECTED_IRQ_GROUP
77 #define ARM_GIC_SELECTED_IRQ_GROUP GRP1S
78 #endif
79
80 #define COMBINE2(a, b) a ## b
81 #define XCOMBINE2(a, b) COMBINE2(a,b)
82 #define GICV3_IRQ_GROUP XCOMBINE2(GICV3_IRQ_GROUP_, ARM_GIC_SELECTED_IRQ_GROUP)
83
84 /*
85 * In ARMv8 for GICv3/v4, ARM suggest to use system register
86 * to access GICC instead of memory map.
87 */
88 #ifdef ARCH_ARM64
89
90 #define GICCREG_READ(gic, reg) ARM64_READ_SYSREG(reg)
91 #define GICCREG_WRITE(gic, reg, val) ARM64_WRITE_SYSREG(reg, (uint64_t)val)
92
93 #else /* ARCH_ARM64 */
94
95 /* For 32bit mode, use different way to access registers */
96 #define GICCREG_READ(gic, reg) COMBINE2(arm_read_,reg)()
97 #define GICCREG_WRITE(gic, reg, val) COMBINE2(arm_write_,reg)(val)
98
99 GEN_CP15_REG_FUNCS(icc_ctlr_el1, 0, c12, c12, 4);
100 GEN_CP15_REG_FUNCS(icc_pmr_el1, 0, c4, c6, 0);
101 GEN_CP15_REG_FUNCS(icc_bpr0_el1, 0, c12, c8, 3);
102 GEN_CP15_REG_FUNCS(icc_iar0_el1, 0, c12, c8, 0);
103 GEN_CP15_REG_FUNCS(icc_eoir0_el1, 0, c12, c8, 1);
104 GEN_CP15_REG_FUNCS(icc_rpr_el1, 0, c12, c11, 3);
105 GEN_CP15_REG_FUNCS(icc_hppir0_el1, 0, c12, c8, 2);
106 GEN_CP15_REG_FUNCS(icc_bpr1_el1, 0, c12, c12, 3);
107 GEN_CP15_REG_FUNCS(icc_iar1_el1, 0, c12, c12, 0);
108 GEN_CP15_REG_FUNCS(icc_eoir1_el1, 0, c12, c12, 1);
109 GEN_CP15_REG_FUNCS(icc_hppir1_el1, 0, c12, c12, 2);
110 GEN_CP15_REG_FUNCS(icc_dir_el1, 0, c12, c11, 1);
111 GEN_CP15_REG_FUNCS(icc_sre_el1, 0, c12, c12, 5);
112 GEN_CP15_REG_FUNCS(icc_igrpen0_el1, 0, c12, c12, 6);
113 GEN_CP15_REG_FUNCS(icc_igrpen1_el1, 0, c12, c12, 7);
114 GEN_CP15_REG_FUNCS(icc_ap0r0_el1, 0, c12, c8, 4);
115 GEN_CP15_REG_FUNCS(icc_ap0r1_el1, 0, c12, c8, 5);
116 GEN_CP15_REG_FUNCS(icc_ap0r2_el1, 0, c12, c8, 6);
117 GEN_CP15_REG_FUNCS(icc_ap0r3_el1, 0, c12, c8, 7);
118 GEN_CP15_REG_FUNCS(icc_ap1r0_el1, 0, c12, c9, 0);
119 GEN_CP15_REG_FUNCS(icc_ap1r1_el1, 0, c12, c9, 1);
120 GEN_CP15_REG_FUNCS(icc_ap1r2_el1, 0, c12, c9, 2);
121 GEN_CP15_REG_FUNCS(icc_ap1r3_el1, 0, c12, c9, 3);
122 GEN_CP15_REG64_FUNCS(icc_sgi1r_el1, 0, c12);
123 GEN_CP15_REG64_FUNCS(icc_asgi1r_el1, 1, c12);
124 GEN_CP15_REG64_FUNCS(icc_sgi0r_el1, 2, c12);
125
126 #endif /* ARCH_ARM64 */
127
128 #if GICV3_IRQ_GROUP == GICV3_IRQ_GROUP_GRP0S
129 #define GICC_PRIMARY_HPPIR icc_hppir0_el1
130 #define GICC_PRIMARY_IAR icc_iar0_el1
131 #define GICC_PRIMARY_EOIR icc_eoir0_el1
132 #define GICC_PRIMARY_SGIR icc_sgi0r_el1
133 #else
134 #define GICC_PRIMARY_HPPIR icc_hppir1_el1
135 #define GICC_PRIMARY_IAR icc_iar1_el1
136 #define GICC_PRIMARY_EOIR icc_eoir1_el1
137 #define GICC_PRIMARY_SGIR icc_sgi1r_el1
138 #endif
139
140 #define GICC_LIMIT (0x0000)
141
142 #else /* GIC_VERSION > 2 */
143
144 #ifndef GICC_OFFSET
145 #define GICC_OFFSET (0x0000)
146 #endif
147
148 #define GICCREG_READ(gic, reg) ({ \
149 ASSERT(gic < NUM_ARM_GICS); \
150 ASSERT(reg >= GICC_OFFSET); \
151 ASSERT(reg < GICC_LIMIT); \
152 mmio_read32((volatile uint32_t *)(arm_gics[(gic)].gicc_vaddr + ((reg) - GICC_OFFSET))); \
153 })
154 #define GICCREG_WRITE(gic, reg, val) ({ \
155 ASSERT(gic < NUM_ARM_GICS); \
156 ASSERT(reg >= GICC_OFFSET); \
157 ASSERT(reg < GICC_LIMIT); \
158 mmio_write32((volatile uint32_t *)(arm_gics[(gic)].gicc_vaddr + ((reg) - GICC_OFFSET)), (val)); \
159 })
160 /* main cpu regs */
161 #define GICC_CTLR (GICC_OFFSET + 0x0000)
162 #define GICC_PMR (GICC_OFFSET + 0x0004)
163 #define GICC_BPR (GICC_OFFSET + 0x0008)
164 #define GICC_IAR (GICC_OFFSET + 0x000c)
165 #define GICC_EOIR (GICC_OFFSET + 0x0010)
166 #define GICC_RPR (GICC_OFFSET + 0x0014)
167 #define GICC_HPPIR (GICC_OFFSET + 0x0018)
168 #define GICC_ABPR (GICC_OFFSET + 0x001c)
169 #define GICC_AIAR (GICC_OFFSET + 0x0020)
170 #define GICC_AEOIR (GICC_OFFSET + 0x0024)
171 #define GICC_AHPPIR (GICC_OFFSET + 0x0028)
172 #define GICC_APR(n) (GICC_OFFSET + 0x00d0 + (n) * 4)
173 #define GICC_NSAPR(n) (GICC_OFFSET + 0x00e0 + (n) * 4)
174 #define GICC_IIDR (GICC_OFFSET + 0x00fc)
175 #if 0 /* GICC_DIR is not currently used by anything */
176 #define GICC_DIR (GICC_OFFSET + 0x1000)
177 #endif
178 #define GICC_LIMIT (GICC_OFFSET + 0x1000)
179 #define GICC_MIN_SIZE (GICC_LIMIT - GICC_OFFSET)
180
181 #if WITH_LIB_SM
182 #define GICC_PRIMARY_HPPIR GICC_AHPPIR
183 #define GICC_PRIMARY_IAR GICC_AIAR
184 #define GICC_PRIMARY_EOIR GICC_AEOIR
185 #else
186 #define GICC_PRIMARY_HPPIR GICC_HPPIR
187 #define GICC_PRIMARY_IAR GICC_IAR
188 #define GICC_PRIMARY_EOIR GICC_EOIR
189 #endif
190
191 #endif /* GIC_VERSION > 2 */
192
193 #ifndef GICD_OFFSET
194 #define GICD_OFFSET (GICC_LIMIT)
195 #endif
196
197 #define GICDREG_READ(gic, reg) ({ \
198 ASSERT(gic < NUM_ARM_GICS); \
199 ASSERT(reg >= GICD_OFFSET); \
200 ASSERT(reg < GICD_LIMIT); \
201 mmio_read32((volatile uint32_t *)(arm_gics[(gic)].gicd_vaddr + ((reg) - GICD_OFFSET))); \
202 })
203 #define GICDREG_WRITE(gic, reg, val) ({ \
204 ASSERT(gic < NUM_ARM_GICS); \
205 ASSERT(reg >= GICD_OFFSET); \
206 ASSERT(reg < GICD_LIMIT); \
207 mmio_write32((volatile uint32_t *)(arm_gics[(gic)].gicd_vaddr + ((reg) - GICD_OFFSET)), (val)); \
208 })
209 /* distribution regs */
210 #define GICD_CTLR (GICD_OFFSET + 0x000)
211 #define GICD_TYPER (GICD_OFFSET + 0x004)
212 #define GICD_IIDR (GICD_OFFSET + 0x008)
213 #define GICD_IGROUPR(n) (GICD_OFFSET + 0x080 + (n) * 4)
214 #define GICD_ISENABLER(n) (GICD_OFFSET + 0x100 + (n) * 4)
215 #define GICD_ICENABLER(n) (GICD_OFFSET + 0x180 + (n) * 4)
216 #define GICD_ISPENDR(n) (GICD_OFFSET + 0x200 + (n) * 4)
217 #define GICD_ICPENDR(n) (GICD_OFFSET + 0x280 + (n) * 4)
218 #define GICD_ISACTIVER(n) (GICD_OFFSET + 0x300 + (n) * 4)
219 #define GICD_ICACTIVER(n) (GICD_OFFSET + 0x380 + (n) * 4)
220 #define GICD_IPRIORITYR(n) (GICD_OFFSET + 0x400 + (n) * 4)
221 #define GICD_ITARGETSR(n) (GICD_OFFSET + 0x800 + (n) * 4)
222 #define GICD_ICFGR(n) (GICD_OFFSET + 0xc00 + (n) * 4)
223 #define GICD_NSACR(n) (GICD_OFFSET + 0xe00 + (n) * 4)
224 #define GICD_SGIR (GICD_OFFSET + 0xf00)
225 #define GICD_CPENDSGIR(n) (GICD_OFFSET + 0xf10 + (n) * 4)
226 #define GICD_SPENDSGIR(n) (GICD_OFFSET + 0xf20 + (n) * 4)
227 #if GIC_VERSION <= 2
228 /* for v3 and higher, these are defined later */
229 #define GICD_LIMIT (GICD_OFFSET + 0x1000)
230 #define GICD_MIN_SIZE (GICD_LIMIT - GICD_OFFSET)
231 #endif /* GIC_VERSION <= 2 */
232
233 #if GIC_VERSION > 2
234 /* some registers of GICD are 64 bit */
235 #define GICDREG_READ64(gic, reg) ({ \
236 ASSERT(gic < NUM_ARM_GICS); \
237 ASSERT(reg >= GICD_OFFSET); \
238 ASSERT(reg < GICD_LIMIT); \
239 mmio_read64((volatile uint64_t *)(arm_gics[(gic)].gicd_vaddr + ((reg) - GICD_OFFSET))); \
240 })
241 #define GICDREG_WRITE64(gic, reg, val) ({ \
242 ASSERT(gic < NUM_ARM_GICS); \
243 ASSERT(reg >= GICD_OFFSET); \
244 ASSERT(reg < GICD_LIMIT); \
245 mmio_write64((volatile uint64_t *)(arm_gics[(gic)].gicd_vaddr + ((reg) - GICD_OFFSET)), (val)); \
246 })
247
248 /* GICv3/v4 Distributor interface */
249 #define GICD_STATUSR (GICD_OFFSET + 0x0010)
250 #define GICD_SETSPI_NSR (GICD_OFFSET + 0x0040)
251 #define GICD_CLRSPI_NSR (GICD_OFFSET + 0x0048)
252 #define GICD_SETSPI_SR (GICD_OFFSET + 0x0050)
253 #define GICD_CLRSPI_SR (GICD_OFFSET + 0x0058)
254 #define GICD_IGRPMODR(n) (GICD_OFFSET + 0x0D00 + (n) * 4)
255 #define GICD_IROUTER(n) (GICD_OFFSET + 0x6000 + (n) * 8)
256 #define GICD_LIMIT (GICD_OFFSET + 0x10000)
257 #define GICD_MIN_SIZE (GICD_LIMIT - GICD_OFFSET)
258
259 /* GICv3/v4 Redistrubutor interface */
260 #if GIC_VERSION == 3
261 #define GICR_CPU_OFFSET(cpu) ((cpu) * 0x20000)
262 #endif
263 #if GIC_VERSION == 4
264 #define GICR_CPU_OFFSET(cpu) ((cpu) * 0x40000)
265 #endif
266
267 #ifndef GICR_OFFSET
268 #define GICR_OFFSET (GICD_LIMIT)
269 #endif
270
271 #define GICRREG_READ(gic, cpu, reg) ({ \
272 ASSERT(gic < NUM_ARM_GICS); \
273 ASSERT(cpu < SMP_MAX_CPUS); \
274 ASSERT(reg >= GICR_OFFSET); \
275 ASSERT(reg < GICR_LIMIT); \
276 mmio_read32((volatile uint32_t *)(arm_gics[(gic)].gicr_vaddr + GICR_CPU_OFFSET(cpu) + ((reg) - GICR_OFFSET))); \
277 })
278 #define GICRREG_WRITE(gic, cpu, reg, val) ({ \
279 ASSERT(gic < NUM_ARM_GICS); \
280 ASSERT(cpu < SMP_MAX_CPUS); \
281 ASSERT(reg >= GICR_OFFSET); \
282 ASSERT(reg < GICR_LIMIT); \
283 mmio_write32((volatile uint32_t *)(arm_gics[(gic)].gicr_vaddr + GICR_CPU_OFFSET(cpu) + ((reg) - GICR_OFFSET)), (val)); \
284 })
285
286 #define GICR_CTRL (GICR_OFFSET + 0x0000)
287 #define GICR_IIDR (GICR_OFFSET + 0x0004)
288 #define GICR_TYPER (GICR_OFFSET + 0x0008)
289 #define GICR_STATUSR (GICR_OFFSET + 0x0010)
290 #define GICR_WAKER (GICR_OFFSET + 0x0014)
291
292 /* The following GICR registers are on separate 64KB page */
293 #define GICR_SGI_OFFSET (GICR_OFFSET + 0x10000)
294 #define GICR_IGROUPR0 (GICR_SGI_OFFSET + 0x0080)
295 #define GICR_ISENABLER0 (GICR_SGI_OFFSET + 0x0100)
296 #define GICR_ICENABLER0 (GICR_SGI_OFFSET + 0x0180)
297 #define GICR_ISPENDR0 (GICR_SGI_OFFSET + 0x0200)
298 #define GICR_ICPENDR0 (GICR_SGI_OFFSET + 0x0280)
299 #define GICR_ISACTIVER0 (GICR_SGI_OFFSET + 0x0300)
300 #define GICR_ICACTIVER0 (GICR_SGI_OFFSET + 0x0380)
301 #define GICR_IPRIORITYR(n) (GICR_SGI_OFFSET + 0x0400 + (n) * 4)
302 #define GICR_ICFGR(n) (GICR_SGI_OFFSET + 0x0C00 + (n) * 4)
303 #define GICR_IGRPMODR0 (GICR_SGI_OFFSET + 0x0D00)
304 #define GICR_NSACR (GICR_SGI_OFFSET + 0x0E00)
305 #define GICR_LIMIT (GICR_SGI_OFFSET + 0x1000)
306 #define GICR_MIN_SIZE (GICR_LIMIT - GICR_OFFSET)
307 #endif /* GIC_VERSION > 2 */
308