xref: /optee_os/core/drivers/gic.c (revision 2ffdd194063da02d2e82a5f671893fb19ba7846c)
1 /*
2  * Copyright (c) 2016, Linaro Limited
3  * Copyright (c) 2014, STMicroelectronics International N.V.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <assert.h>
30 #include <drivers/gic.h>
31 #include <kernel/interrupt.h>
32 #include <kernel/panic.h>
33 #include <util.h>
34 #include <io.h>
35 #include <trace.h>
36 
37 /* Offsets from gic.gicc_base */
38 #define GICC_CTLR		(0x000)
39 #define GICC_PMR		(0x004)
40 #define GICC_IAR		(0x00C)
41 #define GICC_EOIR		(0x010)
42 
43 #define GICC_CTLR_ENABLEGRP0	(1 << 0)
44 #define GICC_CTLR_ENABLEGRP1	(1 << 1)
45 #define GICC_CTLR_FIQEN		(1 << 3)
46 
47 /* Offsets from gic.gicd_base */
48 #define GICD_CTLR		(0x000)
49 #define GICD_TYPER		(0x004)
50 #define GICD_IGROUPR(n)		(0x080 + (n) * 4)
51 #define GICD_ISENABLER(n)	(0x100 + (n) * 4)
52 #define GICD_ICENABLER(n)	(0x180 + (n) * 4)
53 #define GICD_ICPENDR(n)		(0x280 + (n) * 4)
54 #define GICD_IPRIORITYR(n)	(0x400 + (n) * 4)
55 #define GICD_ITARGETSR(n)	(0x800 + (n) * 4)
56 
57 #define GICD_CTLR_ENABLEGRP0	(1 << 0)
58 #define GICD_CTLR_ENABLEGRP1	(1 << 1)
59 
60 /* Number of Private Peripheral Interrupt */
61 #define NUM_PPI	32
62 
63 /* Number of interrupts in one register */
64 #define NUM_INTS_PER_REG	32
65 
66 /* Number of targets in one register */
67 #define NUM_TARGETS_PER_REG	4
68 
69 /* Accessors to access ITARGETSRn */
70 #define ITARGETSR_FIELD_BITS	8
71 #define ITARGETSR_FIELD_MASK	0xff
72 
73 /* Maximum number of interrups a GIC can support */
74 #define GIC_MAX_INTS		1020
75 
76 #define GIC_SPURIOUS_ID		1023
77 
78 #define GICC_IAR_IT_ID_MASK	0x3ff
79 #define GICC_IAR_CPU_ID_MASK	0x7
80 #define GICC_IAR_CPU_ID_SHIFT	10
81 
82 static void gic_op_add(struct itr_chip *chip, size_t it, uint32_t flags);
83 static void gic_op_enable(struct itr_chip *chip, size_t it);
84 static void gic_op_disable(struct itr_chip *chip, size_t it);
85 
86 static const struct itr_ops gic_ops = {
87 	.add = gic_op_add,
88 	.enable = gic_op_enable,
89 	.disable = gic_op_disable,
90 };
91 
92 static size_t probe_max_it(vaddr_t gicc_base, vaddr_t gicd_base)
93 {
94 	int i;
95 	uint32_t old_ctlr;
96 	size_t ret = 0;
97 	const size_t max_regs = ((GIC_MAX_INTS + NUM_INTS_PER_REG - 1) /
98 					NUM_INTS_PER_REG) - 1;
99 
100 	/*
101 	 * Probe which interrupt number is the largest.
102 	 */
103 	old_ctlr = read32(gicc_base + GICC_CTLR);
104 	write32(0, gicc_base + GICC_CTLR);
105 	for (i = max_regs; i >= 0; i--) {
106 		uint32_t old_reg;
107 		uint32_t reg;
108 		int b;
109 
110 		old_reg = read32(gicd_base + GICD_ISENABLER(i));
111 		write32(0xffffffff, gicd_base + GICD_ISENABLER(i));
112 		reg = read32(gicd_base + GICD_ISENABLER(i));
113 		write32(old_reg, gicd_base + GICD_ICENABLER(i));
114 		for (b = NUM_INTS_PER_REG - 1; b >= 0; b--) {
115 			if (BIT32(b) & reg) {
116 				ret = i * NUM_INTS_PER_REG + b;
117 				goto out;
118 			}
119 		}
120 	}
121 out:
122 	write32(old_ctlr, gicc_base + GICC_CTLR);
123 	return ret;
124 }
125 
126 void gic_cpu_init(struct gic_data *gd)
127 {
128 	assert(gd->gicd_base && gd->gicc_base);
129 
130 	/* per-CPU interrupts config:
131 	 * ID0-ID7(SGI)   for Non-secure interrupts
132 	 * ID8-ID15(SGI)  for Secure interrupts.
133 	 * All PPI config as Non-secure interrupts.
134 	 */
135 	write32(0xffff00ff, gd->gicd_base + GICD_IGROUPR(0));
136 
137 	/* Set the priority mask to permit Non-secure interrupts, and to
138 	 * allow the Non-secure world to adjust the priority mask itself
139 	 */
140 	write32(0x80, gd->gicc_base + GICC_PMR);
141 
142 	/* Enable GIC */
143 	write32(GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1 | GICC_CTLR_FIQEN,
144 		gd->gicc_base + GICC_CTLR);
145 }
146 
147 void gic_init(struct gic_data *gd, vaddr_t gicc_base, vaddr_t gicd_base)
148 {
149 	size_t n;
150 
151 	gic_init_base_addr(gd, gicc_base, gicd_base);
152 
153 	for (n = 0; n <= gd->max_it / NUM_INTS_PER_REG; n++) {
154 		/* Disable interrupts */
155 		write32(0xffffffff, gd->gicd_base + GICD_ICENABLER(n));
156 
157 		/* Make interrupts non-pending */
158 		write32(0xffffffff, gd->gicd_base + GICD_ICPENDR(n));
159 
160 		/* Mark interrupts non-secure */
161 		if (n == 0) {
162 			/* per-CPU inerrupts config:
163                          * ID0-ID7(SGI)   for Non-secure interrupts
164                          * ID8-ID15(SGI)  for Secure interrupts.
165                          * All PPI config as Non-secure interrupts.
166 			 */
167 			write32(0xffff00ff, gd->gicd_base + GICD_IGROUPR(n));
168 		} else {
169 			write32(0xffffffff, gd->gicd_base + GICD_IGROUPR(n));
170 		}
171 	}
172 
173 	/* Set the priority mask to permit Non-secure interrupts, and to
174 	 * allow the Non-secure world to adjust the priority mask itself
175 	 */
176 	write32(0x80, gd->gicc_base + GICC_PMR);
177 
178 	/* Enable GIC */
179 	write32(GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1 | GICC_CTLR_FIQEN,
180 		gd->gicc_base + GICC_CTLR);
181 	write32(GICD_CTLR_ENABLEGRP0 | GICD_CTLR_ENABLEGRP1,
182 		gd->gicd_base + GICD_CTLR);
183 }
184 
185 void gic_init_base_addr(struct gic_data *gd, vaddr_t gicc_base,
186 			vaddr_t gicd_base)
187 {
188 	gd->gicc_base = gicc_base;
189 	gd->gicd_base = gicd_base;
190 	gd->max_it = probe_max_it(gicc_base, gicd_base);
191 	gd->chip.ops = &gic_ops;
192 }
193 
194 static void gic_it_add(struct gic_data *gd, size_t it)
195 {
196 	size_t idx = it / NUM_INTS_PER_REG;
197 	uint32_t mask = 1 << (it % NUM_INTS_PER_REG);
198 
199 	/* Disable the interrupt */
200 	write32(mask, gd->gicd_base + GICD_ICENABLER(idx));
201 	/* Make it non-pending */
202 	write32(mask, gd->gicd_base + GICD_ICPENDR(idx));
203 	/* Assign it to group0 */
204 	write32(read32(gd->gicd_base + GICD_IGROUPR(idx)) & ~mask,
205 			gd->gicd_base + GICD_IGROUPR(idx));
206 }
207 
208 static void gic_it_set_cpu_mask(struct gic_data *gd, size_t it,
209 				uint8_t cpu_mask)
210 {
211 	size_t idx __maybe_unused = it / NUM_INTS_PER_REG;
212 	uint32_t mask __maybe_unused = 1 << (it % NUM_INTS_PER_REG);
213 	uint32_t target, target_shift;
214 
215 	/* Assigned to group0 */
216 	assert(!(read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask));
217 
218 	/* Route it to selected CPUs */
219 	target = read32(gd->gicd_base +
220 			GICD_ITARGETSR(it / NUM_TARGETS_PER_REG));
221 	target_shift = (it % NUM_TARGETS_PER_REG) * ITARGETSR_FIELD_BITS;
222 	target &= ~(ITARGETSR_FIELD_MASK << target_shift);
223 	target |= cpu_mask << target_shift;
224 	DMSG("cpu_mask: writing 0x%x to 0x%" PRIxVA,
225 	     target, gd->gicd_base + GICD_ITARGETSR(it / NUM_TARGETS_PER_REG));
226 	write32(target,
227 		gd->gicd_base + GICD_ITARGETSR(it / NUM_TARGETS_PER_REG));
228 	DMSG("cpu_mask: 0x%x\n",
229 	     read32(gd->gicd_base + GICD_ITARGETSR(it / NUM_TARGETS_PER_REG)));
230 }
231 
232 static void gic_it_set_prio(struct gic_data *gd, size_t it, uint8_t prio)
233 {
234 	size_t idx __maybe_unused = it / NUM_INTS_PER_REG;
235 	uint32_t mask __maybe_unused = 1 << (it % NUM_INTS_PER_REG);
236 
237 	/* Assigned to group0 */
238 	assert(!(read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask));
239 
240 	/* Set prio it to selected CPUs */
241 	DMSG("prio: writing 0x%x to 0x%" PRIxVA,
242 		prio, gd->gicd_base + GICD_IPRIORITYR(0) + it);
243 	write8(prio, gd->gicd_base + GICD_IPRIORITYR(0) + it);
244 }
245 
246 static void gic_it_enable(struct gic_data *gd, size_t it)
247 {
248 	size_t idx = it / NUM_INTS_PER_REG;
249 	uint32_t mask = 1 << (it % NUM_INTS_PER_REG);
250 
251 	/* Assigned to group0 */
252 	assert(!(read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask));
253 	/* Not enabled yet */
254 	assert(!(read32(gd->gicd_base + GICD_ISENABLER(idx)) & mask));
255 
256 	/* Enable the interrupt */
257 	write32(mask, gd->gicd_base + GICD_ISENABLER(idx));
258 }
259 
260 static void gic_it_disable(struct gic_data *gd, size_t it)
261 {
262 	size_t idx = it / NUM_INTS_PER_REG;
263 	uint32_t mask = 1 << (it % NUM_INTS_PER_REG);
264 
265 	/* Assigned to group0 */
266 	assert(!(read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask));
267 
268 	/* Disable the interrupt */
269 	write32(mask, gd->gicd_base + GICD_ICENABLER(idx));
270 }
271 
272 static uint32_t gic_read_iar(struct gic_data *gd)
273 {
274 	return read32(gd->gicc_base + GICC_IAR);
275 }
276 
277 static void gic_write_eoir(struct gic_data *gd, uint32_t eoir)
278 {
279 	write32(eoir, gd->gicc_base + GICC_EOIR);
280 }
281 
282 static bool gic_it_is_enabled(struct gic_data *gd, size_t it)
283 {
284 	size_t idx = it / NUM_INTS_PER_REG;
285 	uint32_t mask = 1 << (it % NUM_INTS_PER_REG);
286 	return !!(read32(gd->gicd_base + GICD_ISENABLER(idx)) & mask);
287 }
288 
289 static bool __maybe_unused gic_it_get_group(struct gic_data *gd, size_t it)
290 {
291 	size_t idx = it / NUM_INTS_PER_REG;
292 	uint32_t mask = 1 << (it % NUM_INTS_PER_REG);
293 	return !!(read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask);
294 }
295 
296 static uint32_t __maybe_unused gic_it_get_target(struct gic_data *gd, size_t it)
297 {
298 	size_t reg_idx = it / NUM_TARGETS_PER_REG;
299 	uint32_t target_shift = (it % NUM_TARGETS_PER_REG) *
300 				ITARGETSR_FIELD_BITS;
301 	uint32_t target_mask = ITARGETSR_FIELD_MASK << target_shift;
302 	uint32_t target =
303 		read32(gd->gicd_base + GICD_ITARGETSR(reg_idx)) & target_mask;
304 
305 	target = target >> target_shift;
306 	return target;
307 }
308 
309 void gic_dump_state(struct gic_data *gd)
310 {
311 	int i;
312 
313 	DMSG("GICC_CTLR: 0x%x", read32(gd->gicc_base + GICC_CTLR));
314 	DMSG("GICD_CTLR: 0x%x", read32(gd->gicd_base + GICD_CTLR));
315 
316 	for (i = 0; i < (int)gd->max_it; i++) {
317 		if (gic_it_is_enabled(gd, i)) {
318 			DMSG("irq%d: enabled, group:%d, target:%x", i,
319 			     gic_it_get_group(gd, i), gic_it_get_target(gd, i));
320 		}
321 	}
322 }
323 
324 void gic_it_handle(struct gic_data *gd)
325 {
326 	uint32_t iar;
327 	uint32_t id;
328 
329 	iar = gic_read_iar(gd);
330 	id = iar & GICC_IAR_IT_ID_MASK;
331 
332 	if (id == GIC_SPURIOUS_ID)
333 		DMSG("ignoring spurious interrupt");
334 	else
335 		itr_handle(id);
336 
337 	gic_write_eoir(gd, iar);
338 }
339 
340 static void gic_op_add(struct itr_chip *chip, size_t it,
341 		       uint32_t flags __unused)
342 {
343 	struct gic_data *gd = container_of(chip, struct gic_data, chip);
344 
345 	if (it >= gd->max_it)
346 		panic();
347 
348 	gic_it_add(gd, it);
349 	/* Set the CPU mask to deliver interrupts to any online core */
350 	gic_it_set_cpu_mask(gd, it, 0xff);
351 	gic_it_set_prio(gd, it, 0x1);
352 }
353 
354 static void gic_op_enable(struct itr_chip *chip, size_t it)
355 {
356 	struct gic_data *gd = container_of(chip, struct gic_data, chip);
357 
358 	if (it >= gd->max_it)
359 		panic();
360 
361 	gic_it_enable(gd, it);
362 }
363 
364 static void gic_op_disable(struct itr_chip *chip, size_t it)
365 {
366 	struct gic_data *gd = container_of(chip, struct gic_data, chip);
367 
368 	if (it >= gd->max_it)
369 		panic();
370 
371 	gic_it_disable(gd, it);
372 }
373