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