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