gic.c revision 299117
1/*-
2 * Copyright (c) 2011 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * Developed by Damjan Marion <damjan.marion@gmail.com>
6 *
7 * Based on OMAP4 GIC code by Ben Gray
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. The name of the company nor the name of the author may be used to
18 *    endorse or promote products derived from this software without specific
19 *    prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/arm/arm/gic.c 299117 2016-05-05 13:31:19Z skra $");
36
37#include "opt_platform.h"
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/bus.h>
42#include <sys/kernel.h>
43#include <sys/ktr.h>
44#include <sys/module.h>
45#include <sys/malloc.h>
46#include <sys/rman.h>
47#include <sys/pcpu.h>
48#include <sys/proc.h>
49#include <sys/cpuset.h>
50#include <sys/lock.h>
51#include <sys/mutex.h>
52#include <sys/smp.h>
53#ifdef INTRNG
54#include <sys/sched.h>
55#endif
56#include <machine/bus.h>
57#include <machine/intr.h>
58#include <machine/smp.h>
59
60#include <dev/fdt/fdt_common.h>
61#include <dev/ofw/openfirm.h>
62#include <dev/ofw/ofw_bus.h>
63#include <dev/ofw/ofw_bus_subr.h>
64
65#ifdef INTRNG
66#include "pic_if.h"
67#endif
68
69#define GIC_DEBUG_SPURIOUS
70
71/* We are using GICv2 register naming */
72
73/* Distributor Registers */
74#define GICD_CTLR		0x000			/* v1 ICDDCR */
75#define GICD_TYPER		0x004			/* v1 ICDICTR */
76#define GICD_IIDR		0x008			/* v1 ICDIIDR */
77#define GICD_IGROUPR(n)		(0x0080 + ((n) * 4))	/* v1 ICDISER */
78#define GICD_ISENABLER(n)	(0x0100 + ((n) * 4))	/* v1 ICDISER */
79#define GICD_ICENABLER(n)	(0x0180 + ((n) * 4))	/* v1 ICDICER */
80#define GICD_ISPENDR(n)		(0x0200 + ((n) * 4))	/* v1 ICDISPR */
81#define GICD_ICPENDR(n)		(0x0280 + ((n) * 4))	/* v1 ICDICPR */
82#define GICD_ICACTIVER(n)	(0x0380 + ((n) * 4))	/* v1 ICDABR */
83#define GICD_IPRIORITYR(n)	(0x0400 + ((n) * 4))	/* v1 ICDIPR */
84#define GICD_ITARGETSR(n)	(0x0800 + ((n) * 4))	/* v1 ICDIPTR */
85#define GICD_ICFGR(n)		(0x0C00 + ((n) * 4))	/* v1 ICDICFR */
86#define GICD_SGIR(n)		(0x0F00 + ((n) * 4))	/* v1 ICDSGIR */
87#define  GICD_SGI_TARGET_SHIFT	16
88
89/* CPU Registers */
90#define GICC_CTLR		0x0000			/* v1 ICCICR */
91#define GICC_PMR		0x0004			/* v1 ICCPMR */
92#define GICC_BPR		0x0008			/* v1 ICCBPR */
93#define GICC_IAR		0x000C			/* v1 ICCIAR */
94#define GICC_EOIR		0x0010			/* v1 ICCEOIR */
95#define GICC_RPR		0x0014			/* v1 ICCRPR */
96#define GICC_HPPIR		0x0018			/* v1 ICCHPIR */
97#define GICC_ABPR		0x001C			/* v1 ICCABPR */
98#define GICC_IIDR		0x00FC			/* v1 ICCIIDR*/
99
100#define	GIC_FIRST_SGI		 0	/* Irqs 0-15 are SGIs/IPIs. */
101#define	GIC_LAST_SGI		15
102#define	GIC_FIRST_PPI		16	/* Irqs 16-31 are private (per */
103#define	GIC_LAST_PPI		31	/* core) peripheral interrupts. */
104#define	GIC_FIRST_SPI		32	/* Irqs 32+ are shared peripherals. */
105
106/* First bit is a polarity bit (0 - low, 1 - high) */
107#define GICD_ICFGR_POL_LOW	(0 << 0)
108#define GICD_ICFGR_POL_HIGH	(1 << 0)
109#define GICD_ICFGR_POL_MASK	0x1
110/* Second bit is a trigger bit (0 - level, 1 - edge) */
111#define GICD_ICFGR_TRIG_LVL	(0 << 1)
112#define GICD_ICFGR_TRIG_EDGE	(1 << 1)
113#define GICD_ICFGR_TRIG_MASK	0x2
114
115#ifndef	GIC_DEFAULT_ICFGR_INIT
116#define	GIC_DEFAULT_ICFGR_INIT	0x00000000
117#endif
118
119#ifdef INTRNG
120struct gic_irqsrc {
121	struct intr_irqsrc	gi_isrc;
122	uint32_t		gi_irq;
123	enum intr_polarity	gi_pol;
124	enum intr_trigger	gi_trig;
125#define GI_FLAG_EARLY_EOI	(1 << 0)
126	u_int			gi_flags;
127};
128
129static u_int gic_irq_cpu;
130static int arm_gic_intr(void *);
131static int arm_gic_bind_intr(device_t dev, struct intr_irqsrc *isrc);
132
133#ifdef SMP
134static u_int sgi_to_ipi[GIC_LAST_SGI - GIC_FIRST_SGI + 1];
135static u_int sgi_first_unused = GIC_FIRST_SGI;
136#endif
137#endif
138
139#ifdef INTRNG
140struct arm_gic_range {
141	uint64_t bus;
142	uint64_t host;
143	uint64_t size;
144};
145
146struct arm_gic_devinfo {
147	struct ofw_bus_devinfo	obdinfo;
148	struct resource_list	rl;
149};
150#endif
151
152struct arm_gic_softc {
153	device_t		gic_dev;
154#ifdef INTRNG
155	void *			gic_intrhand;
156	struct gic_irqsrc *	gic_irqs;
157#endif
158	struct resource *	gic_res[3];
159	bus_space_tag_t		gic_c_bst;
160	bus_space_tag_t		gic_d_bst;
161	bus_space_handle_t	gic_c_bsh;
162	bus_space_handle_t	gic_d_bsh;
163	uint8_t			ver;
164	struct mtx		mutex;
165	uint32_t		nirqs;
166#ifdef GIC_DEBUG_SPURIOUS
167	uint32_t		last_irq[MAXCPU];
168#endif
169
170#ifdef INTRNG
171	/* FDT child data */
172	pcell_t			addr_cells;
173	pcell_t			size_cells;
174	int			nranges;
175	struct arm_gic_range *	ranges;
176#endif
177};
178
179#ifdef INTRNG
180#define GIC_INTR_ISRC(sc, irq)	(&sc->gic_irqs[irq].gi_isrc)
181#endif
182
183static struct resource_spec arm_gic_spec[] = {
184	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },	/* Distributor registers */
185	{ SYS_RES_MEMORY,	1,	RF_ACTIVE },	/* CPU Interrupt Intf. registers */
186#ifdef INTRNG
187	{ SYS_RES_IRQ,	  0, RF_ACTIVE | RF_OPTIONAL }, /* Parent interrupt */
188#endif
189	{ -1, 0 }
190};
191
192static u_int arm_gic_map[MAXCPU];
193
194static struct arm_gic_softc *gic_sc = NULL;
195
196#define	gic_c_read_4(_sc, _reg)		\
197    bus_space_read_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg))
198#define	gic_c_write_4(_sc, _reg, _val)		\
199    bus_space_write_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg), (_val))
200#define	gic_d_read_4(_sc, _reg)		\
201    bus_space_read_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg))
202#define	gic_d_write_1(_sc, _reg, _val)		\
203    bus_space_write_1((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg), (_val))
204#define	gic_d_write_4(_sc, _reg, _val)		\
205    bus_space_write_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg), (_val))
206
207#ifndef INTRNG
208static int gic_config_irq(int irq, enum intr_trigger trig,
209    enum intr_polarity pol);
210static void gic_post_filter(void *);
211#endif
212
213static struct ofw_compat_data compat_data[] = {
214	{"arm,gic",		true},	/* Non-standard, used in FreeBSD dts. */
215	{"arm,gic-400",		true},
216	{"arm,cortex-a15-gic",	true},
217	{"arm,cortex-a9-gic",	true},
218	{"arm,cortex-a7-gic",	true},
219	{"arm,arm11mp-gic",	true},
220	{"brcm,brahma-b15-gic",	true},
221	{"qcom,msm-qgic2",	true},
222	{NULL,			false}
223};
224
225static int
226arm_gic_probe(device_t dev)
227{
228
229	if (!ofw_bus_status_okay(dev))
230		return (ENXIO);
231
232	if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
233		return (ENXIO);
234	device_set_desc(dev, "ARM Generic Interrupt Controller");
235	return (BUS_PROBE_DEFAULT);
236}
237
238#ifdef INTRNG
239static inline void
240gic_irq_unmask(struct arm_gic_softc *sc, u_int irq)
241{
242
243	gic_d_write_4(sc, GICD_ISENABLER(irq >> 5), (1UL << (irq & 0x1F)));
244}
245
246static inline void
247gic_irq_mask(struct arm_gic_softc *sc, u_int irq)
248{
249
250	gic_d_write_4(sc, GICD_ICENABLER(irq >> 5), (1UL << (irq & 0x1F)));
251}
252#endif
253
254static uint8_t
255gic_cpu_mask(struct arm_gic_softc *sc)
256{
257	uint32_t mask;
258	int i;
259
260	/* Read the current cpuid mask by reading ITARGETSR{0..7} */
261	for (i = 0; i < 8; i++) {
262		mask = gic_d_read_4(sc, GICD_ITARGETSR(i));
263		if (mask != 0)
264			break;
265	}
266	/* No mask found, assume we are on CPU interface 0 */
267	if (mask == 0)
268		return (1);
269
270	/* Collect the mask in the lower byte */
271	mask |= mask >> 16;
272	mask |= mask >> 8;
273
274	return (mask);
275}
276
277#ifdef SMP
278#ifdef INTRNG
279static void
280arm_gic_init_secondary(device_t dev)
281{
282	struct arm_gic_softc *sc = device_get_softc(dev);
283	u_int irq, cpu;
284
285	/* Set the mask so we can find this CPU to send it IPIs */
286	cpu = PCPU_GET(cpuid);
287	arm_gic_map[cpu] = gic_cpu_mask(sc);
288
289	for (irq = 0; irq < sc->nirqs; irq += 4)
290		gic_d_write_4(sc, GICD_IPRIORITYR(irq >> 2), 0);
291
292	/* Set all the interrupts to be in Group 0 (secure) */
293	for (irq = 0; irq < sc->nirqs; irq += 32) {
294		gic_d_write_4(sc, GICD_IGROUPR(irq >> 5), 0);
295	}
296
297	/* Enable CPU interface */
298	gic_c_write_4(sc, GICC_CTLR, 1);
299
300	/* Set priority mask register. */
301	gic_c_write_4(sc, GICC_PMR, 0xff);
302
303	/* Enable interrupt distribution */
304	gic_d_write_4(sc, GICD_CTLR, 0x01);
305
306	/* Unmask attached SGI interrupts. */
307	for (irq = GIC_FIRST_SGI; irq <= GIC_LAST_SGI; irq++)
308		if (intr_isrc_init_on_cpu(GIC_INTR_ISRC(sc, irq), cpu))
309			gic_irq_unmask(sc, irq);
310
311	/* Unmask attached PPI interrupts. */
312	for (irq = GIC_FIRST_PPI; irq <= GIC_LAST_PPI; irq++)
313		if (intr_isrc_init_on_cpu(GIC_INTR_ISRC(sc, irq), cpu))
314			gic_irq_unmask(sc, irq);
315}
316#else
317static void
318arm_gic_init_secondary(device_t dev)
319{
320	struct arm_gic_softc *sc = device_get_softc(dev);
321	int i;
322
323	/* Set the mask so we can find this CPU to send it IPIs */
324	arm_gic_map[PCPU_GET(cpuid)] = gic_cpu_mask(sc);
325
326	for (i = 0; i < sc->nirqs; i += 4)
327		gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
328
329	/* Set all the interrupts to be in Group 0 (secure) */
330	for (i = 0; i < sc->nirqs; i += 32) {
331		gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0);
332	}
333
334	/* Enable CPU interface */
335	gic_c_write_4(sc, GICC_CTLR, 1);
336
337	/* Set priority mask register. */
338	gic_c_write_4(sc, GICC_PMR, 0xff);
339
340	/* Enable interrupt distribution */
341	gic_d_write_4(sc, GICD_CTLR, 0x01);
342
343	/*
344	 * Activate the timer interrupts: virtual, secure, and non-secure.
345	 */
346	gic_d_write_4(sc, GICD_ISENABLER(27 >> 5), (1UL << (27 & 0x1F)));
347	gic_d_write_4(sc, GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F)));
348	gic_d_write_4(sc, GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F)));
349}
350#endif /* INTRNG */
351#endif /* SMP */
352
353#ifndef INTRNG
354int
355gic_decode_fdt(phandle_t iparent, pcell_t *intr, int *interrupt,
356    int *trig, int *pol)
357{
358	static u_int num_intr_cells;
359	static phandle_t self;
360	struct ofw_compat_data *ocd;
361
362	if (self == 0) {
363		for (ocd = compat_data; ocd->ocd_str != NULL; ocd++) {
364			if (fdt_is_compatible(iparent, ocd->ocd_str)) {
365				self = iparent;
366				break;
367			}
368		}
369	}
370	if (self != iparent)
371		return (ENXIO);
372
373	if (num_intr_cells == 0) {
374		if (OF_searchencprop(OF_node_from_xref(iparent),
375		    "#interrupt-cells", &num_intr_cells,
376		    sizeof(num_intr_cells)) == -1) {
377			num_intr_cells = 1;
378		}
379	}
380
381	if (num_intr_cells == 1) {
382		*interrupt = fdt32_to_cpu(intr[0]);
383		*trig = INTR_TRIGGER_CONFORM;
384		*pol = INTR_POLARITY_CONFORM;
385	} else {
386		if (fdt32_to_cpu(intr[0]) == 0)
387			*interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_SPI;
388		else
389			*interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_PPI;
390		/*
391		 * In intr[2], bits[3:0] are trigger type and level flags.
392		 *   1 = low-to-high edge triggered
393		 *   2 = high-to-low edge triggered
394		 *   4 = active high level-sensitive
395		 *   8 = active low level-sensitive
396		 * The hardware only supports active-high-level or rising-edge
397		 * for SPIs
398		 */
399		if (*interrupt >= GIC_FIRST_SPI &&
400		    fdt32_to_cpu(intr[2]) & 0x0a) {
401			printf("unsupported trigger/polarity configuration "
402			    "0x%02x\n", fdt32_to_cpu(intr[2]) & 0x0f);
403		}
404		*pol  = INTR_POLARITY_CONFORM;
405		if (fdt32_to_cpu(intr[2]) & 0x03)
406			*trig = INTR_TRIGGER_EDGE;
407		else
408			*trig = INTR_TRIGGER_LEVEL;
409	}
410	return (0);
411}
412#endif
413
414#ifdef INTRNG
415static inline intptr_t
416gic_xref(device_t dev)
417{
418#ifdef FDT
419	return (OF_xref_from_node(ofw_bus_get_node(dev)));
420#else
421	return (0);
422#endif
423}
424
425static int
426arm_gic_register_isrcs(struct arm_gic_softc *sc, uint32_t num)
427{
428	int error;
429	uint32_t irq;
430	struct gic_irqsrc *irqs;
431	struct intr_irqsrc *isrc;
432	const char *name;
433
434	irqs = malloc(num * sizeof(struct gic_irqsrc), M_DEVBUF,
435	    M_WAITOK | M_ZERO);
436
437	name = device_get_nameunit(sc->gic_dev);
438	for (irq = 0; irq < num; irq++) {
439		irqs[irq].gi_irq = irq;
440		irqs[irq].gi_pol = INTR_POLARITY_CONFORM;
441		irqs[irq].gi_trig = INTR_TRIGGER_CONFORM;
442
443		isrc = &irqs[irq].gi_isrc;
444		if (irq <= GIC_LAST_SGI) {
445			error = intr_isrc_register(isrc, sc->gic_dev,
446			    INTR_ISRCF_IPI, "%s,i%u", name, irq - GIC_FIRST_SGI);
447		} else if (irq <= GIC_LAST_PPI) {
448			error = intr_isrc_register(isrc, sc->gic_dev,
449			    INTR_ISRCF_PPI, "%s,p%u", name, irq - GIC_FIRST_PPI);
450		} else {
451			error = intr_isrc_register(isrc, sc->gic_dev, 0,
452			    "%s,s%u", name, irq - GIC_FIRST_SPI);
453		}
454		if (error != 0) {
455			/* XXX call intr_isrc_deregister() */
456			free(irqs, M_DEVBUF);
457			return (error);
458		}
459	}
460	sc->gic_irqs = irqs;
461	sc->nirqs = num;
462	return (0);
463}
464
465static int
466arm_gic_fill_ranges(phandle_t node, struct arm_gic_softc *sc)
467{
468	pcell_t host_cells;
469	cell_t *base_ranges;
470	ssize_t nbase_ranges;
471	int i, j, k;
472
473	host_cells = 1;
474	OF_getencprop(OF_parent(node), "#address-cells", &host_cells,
475	    sizeof(host_cells));
476	sc->addr_cells = 2;
477	OF_getencprop(node, "#address-cells", &sc->addr_cells,
478	    sizeof(sc->addr_cells));
479	sc->size_cells = 2;
480	OF_getencprop(node, "#size-cells", &sc->size_cells,
481	    sizeof(sc->size_cells));
482
483	nbase_ranges = OF_getproplen(node, "ranges");
484	if (nbase_ranges < 0)
485		return (-1);
486	sc->nranges = nbase_ranges / sizeof(cell_t) /
487	    (sc->addr_cells + host_cells + sc->size_cells);
488	if (sc->nranges == 0)
489		return (0);
490
491	sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]),
492	    M_DEVBUF, M_WAITOK);
493	base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
494	OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
495
496	for (i = 0, j = 0; i < sc->nranges; i++) {
497		sc->ranges[i].bus = 0;
498		for (k = 0; k < sc->addr_cells; k++) {
499			sc->ranges[i].bus <<= 32;
500			sc->ranges[i].bus |= base_ranges[j++];
501		}
502		sc->ranges[i].host = 0;
503		for (k = 0; k < host_cells; k++) {
504			sc->ranges[i].host <<= 32;
505			sc->ranges[i].host |= base_ranges[j++];
506		}
507		sc->ranges[i].size = 0;
508		for (k = 0; k < sc->size_cells; k++) {
509			sc->ranges[i].size <<= 32;
510			sc->ranges[i].size |= base_ranges[j++];
511		}
512	}
513
514	free(base_ranges, M_DEVBUF);
515	return (sc->nranges);
516}
517
518static bool
519arm_gic_add_children(device_t dev)
520{
521	struct arm_gic_softc *sc;
522	struct arm_gic_devinfo *dinfo;
523	phandle_t child, node;
524	device_t cdev;
525
526	sc = device_get_softc(dev);
527	node = ofw_bus_get_node(dev);
528
529	/* If we have no children don't probe for them */
530	child = OF_child(node);
531	if (child == 0)
532		return (false);
533
534	if (arm_gic_fill_ranges(node, sc) < 0) {
535		device_printf(dev, "Have a child, but no ranges\n");
536		return (false);
537	}
538
539	for (; child != 0; child = OF_peer(child)) {
540		dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO);
541
542		if (ofw_bus_gen_setup_devinfo(&dinfo->obdinfo, child) != 0) {
543			free(dinfo, M_DEVBUF);
544			continue;
545		}
546
547		resource_list_init(&dinfo->rl);
548		ofw_bus_reg_to_rl(dev, child, sc->addr_cells,
549		    sc->size_cells, &dinfo->rl);
550
551		cdev = device_add_child(dev, NULL, -1);
552		if (cdev == NULL) {
553			device_printf(dev, "<%s>: device_add_child failed\n",
554			    dinfo->obdinfo.obd_name);
555			resource_list_free(&dinfo->rl);
556			ofw_bus_gen_destroy_devinfo(&dinfo->obdinfo);
557			free(dinfo, M_DEVBUF);
558			continue;
559		}
560		device_set_ivars(cdev, dinfo);
561	}
562
563	return (true);
564}
565#endif
566
567static int
568arm_gic_attach(device_t dev)
569{
570	struct		arm_gic_softc *sc;
571	int		i;
572	uint32_t	icciidr, mask, nirqs;
573#ifdef INTRNG
574	phandle_t	pxref;
575	intptr_t	xref = gic_xref(dev);
576#endif
577
578	if (gic_sc)
579		return (ENXIO);
580
581	sc = device_get_softc(dev);
582
583	if (bus_alloc_resources(dev, arm_gic_spec, sc->gic_res)) {
584		device_printf(dev, "could not allocate resources\n");
585		return (ENXIO);
586	}
587
588	sc->gic_dev = dev;
589	gic_sc = sc;
590
591	/* Initialize mutex */
592	mtx_init(&sc->mutex, "GIC lock", "", MTX_SPIN);
593
594	/* Distributor Interface */
595	sc->gic_d_bst = rman_get_bustag(sc->gic_res[0]);
596	sc->gic_d_bsh = rman_get_bushandle(sc->gic_res[0]);
597
598	/* CPU Interface */
599	sc->gic_c_bst = rman_get_bustag(sc->gic_res[1]);
600	sc->gic_c_bsh = rman_get_bushandle(sc->gic_res[1]);
601
602	/* Disable interrupt forwarding to the CPU interface */
603	gic_d_write_4(sc, GICD_CTLR, 0x00);
604
605	/* Get the number of interrupts */
606	nirqs = gic_d_read_4(sc, GICD_TYPER);
607	nirqs = 32 * ((nirqs & 0x1f) + 1);
608
609#ifdef INTRNG
610	if (arm_gic_register_isrcs(sc, nirqs)) {
611		device_printf(dev, "could not register irqs\n");
612		goto cleanup;
613	}
614#else
615	sc->nirqs = nirqs;
616
617	/* Set up function pointers */
618	arm_post_filter = gic_post_filter;
619	arm_config_irq = gic_config_irq;
620#endif
621
622	icciidr = gic_c_read_4(sc, GICC_IIDR);
623	device_printf(dev,"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n",
624			icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf,
625			(icciidr & 0xfff), sc->nirqs);
626
627	/* Set all global interrupts to be level triggered, active low. */
628	for (i = 32; i < sc->nirqs; i += 16) {
629		gic_d_write_4(sc, GICD_ICFGR(i >> 4), GIC_DEFAULT_ICFGR_INIT);
630	}
631
632	/* Disable all interrupts. */
633	for (i = 32; i < sc->nirqs; i += 32) {
634		gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF);
635	}
636
637	/* Find the current cpu mask */
638	mask = gic_cpu_mask(sc);
639	/* Set the mask so we can find this CPU to send it IPIs */
640	arm_gic_map[PCPU_GET(cpuid)] = mask;
641	/* Set all four targets to this cpu */
642	mask |= mask << 8;
643	mask |= mask << 16;
644
645	for (i = 0; i < sc->nirqs; i += 4) {
646		gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
647		if (i > 32) {
648			gic_d_write_4(sc, GICD_ITARGETSR(i >> 2), mask);
649		}
650	}
651
652	/* Set all the interrupts to be in Group 0 (secure) */
653	for (i = 0; i < sc->nirqs; i += 32) {
654		gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0);
655	}
656
657	/* Enable CPU interface */
658	gic_c_write_4(sc, GICC_CTLR, 1);
659
660	/* Set priority mask register. */
661	gic_c_write_4(sc, GICC_PMR, 0xff);
662
663	/* Enable interrupt distribution */
664	gic_d_write_4(sc, GICD_CTLR, 0x01);
665#ifndef INTRNG
666	return (0);
667#else
668	/*
669	 * Now, when everything is initialized, it's right time to
670	 * register interrupt controller to interrupt framefork.
671	 */
672	if (intr_pic_register(dev, xref) != 0) {
673		device_printf(dev, "could not register PIC\n");
674		goto cleanup;
675	}
676
677	/*
678	 * Controller is root if:
679	 * - doesn't have interrupt parent
680	 * - his interrupt parent is this controller
681	 */
682	pxref = ofw_bus_find_iparent(ofw_bus_get_node(dev));
683	if (pxref == 0 || xref == pxref) {
684		if (intr_pic_claim_root(dev, xref, arm_gic_intr, sc,
685		    GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) {
686			device_printf(dev, "could not set PIC as a root\n");
687			intr_pic_deregister(dev, xref);
688			goto cleanup;
689		}
690	} else {
691		if (sc->gic_res[2] == NULL) {
692			device_printf(dev,
693			    "not root PIC must have defined interrupt\n");
694			intr_pic_deregister(dev, xref);
695			goto cleanup;
696		}
697		if (bus_setup_intr(dev, sc->gic_res[2], INTR_TYPE_CLK,
698		    arm_gic_intr, NULL, sc, &sc->gic_intrhand)) {
699			device_printf(dev, "could not setup irq handler\n");
700			intr_pic_deregister(dev, xref);
701			goto cleanup;
702		}
703	}
704
705	OF_device_register_xref(xref, dev);
706
707	/* If we have children probe and attach them */
708	if (arm_gic_add_children(dev)) {
709		bus_generic_probe(dev);
710		return (bus_generic_attach(dev));
711	}
712
713	return (0);
714
715cleanup:
716	/*
717	 * XXX - not implemented arm_gic_detach() should be called !
718	 */
719	if (sc->gic_irqs != NULL)
720		free(sc->gic_irqs, M_DEVBUF);
721	bus_release_resources(dev, arm_gic_spec, sc->gic_res);
722	return(ENXIO);
723#endif
724}
725
726#ifdef INTRNG
727static struct resource *
728arm_gic_alloc_resource(device_t bus, device_t child, int type, int *rid,
729    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
730{
731	struct arm_gic_softc *sc;
732	struct arm_gic_devinfo *di;
733	struct resource_list_entry *rle;
734	int j;
735
736	KASSERT(type == SYS_RES_MEMORY, ("Invalid resoure type %x", type));
737
738	sc = device_get_softc(bus);
739
740	/*
741	 * Request for the default allocation with a given rid: use resource
742	 * list stored in the local device info.
743	 */
744	if (RMAN_IS_DEFAULT_RANGE(start, end)) {
745		if ((di = device_get_ivars(child)) == NULL)
746			return (NULL);
747
748		if (type == SYS_RES_IOPORT)
749			type = SYS_RES_MEMORY;
750
751		rle = resource_list_find(&di->rl, type, *rid);
752		if (rle == NULL) {
753			if (bootverbose)
754				device_printf(bus, "no default resources for "
755				    "rid = %d, type = %d\n", *rid, type);
756			return (NULL);
757		}
758		start = rle->start;
759		end = rle->end;
760		count = rle->count;
761	}
762
763	/* Remap through ranges property */
764	for (j = 0; j < sc->nranges; j++) {
765		if (start >= sc->ranges[j].bus && end <
766		    sc->ranges[j].bus + sc->ranges[j].size) {
767			start -= sc->ranges[j].bus;
768			start += sc->ranges[j].host;
769			end -= sc->ranges[j].bus;
770			end += sc->ranges[j].host;
771			break;
772		}
773	}
774	if (j == sc->nranges && sc->nranges != 0) {
775		if (bootverbose)
776			device_printf(bus, "Could not map resource "
777			    "%#jx-%#jx\n", (uintmax_t)start, (uintmax_t)end);
778
779		return (NULL);
780	}
781
782	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
783	    count, flags));
784}
785
786static const struct ofw_bus_devinfo *
787arm_gic_ofw_get_devinfo(device_t bus __unused, device_t child)
788{
789	struct arm_gic_devinfo *di;
790
791	di = device_get_ivars(child);
792
793	return (&di->obdinfo);
794}
795
796static int
797arm_gic_intr(void *arg)
798{
799	struct arm_gic_softc *sc = arg;
800	struct gic_irqsrc *gi;
801	uint32_t irq_active_reg, irq;
802	struct trapframe *tf;
803
804	irq_active_reg = gic_c_read_4(sc, GICC_IAR);
805	irq = irq_active_reg & 0x3FF;
806
807	/*
808	 * 1. We do EOI here because recent read value from active interrupt
809	 *    register must be used for it. Another approach is to save this
810	 *    value into associated interrupt source.
811	 * 2. EOI must be done on same CPU where interrupt has fired. Thus
812	 *    we must ensure that interrupted thread does not migrate to
813	 *    another CPU.
814	 * 3. EOI cannot be delayed by any preemption which could happen on
815	 *    critical_exit() used in MI intr code, when interrupt thread is
816	 *    scheduled. See next point.
817	 * 4. IPI_RENDEZVOUS assumes that no preemption is permitted during
818	 *    an action and any use of critical_exit() could break this
819	 *    assumption. See comments within smp_rendezvous_action().
820	 * 5. We always return FILTER_HANDLED as this is an interrupt
821	 *    controller dispatch function. Otherwise, in cascaded interrupt
822	 *    case, the whole interrupt subtree would be masked.
823	 */
824
825	if (irq >= sc->nirqs) {
826#ifdef GIC_DEBUG_SPURIOUS
827		device_printf(sc->gic_dev,
828		    "Spurious interrupt detected: last irq: %d on CPU%d\n",
829		    sc->last_irq[PCPU_GET(cpuid)], PCPU_GET(cpuid));
830#endif
831		return (FILTER_HANDLED);
832	}
833
834	tf = curthread->td_intr_frame;
835dispatch_irq:
836	gi = sc->gic_irqs + irq;
837	/*
838	 * Note that GIC_FIRST_SGI is zero and is not used in 'if' statement
839	 * as compiler complains that comparing u_int >= 0 is always true.
840	 */
841	if (irq <= GIC_LAST_SGI) {
842#ifdef SMP
843		/* Call EOI for all IPI before dispatch. */
844		gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
845		intr_ipi_dispatch(sgi_to_ipi[gi->gi_irq], tf);
846		goto next_irq;
847#else
848		device_printf(sc->gic_dev, "SGI %u on UP system detected\n",
849		    irq - GIC_FIRST_SGI);
850		gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
851		goto next_irq;
852#endif
853	}
854
855#ifdef GIC_DEBUG_SPURIOUS
856	sc->last_irq[PCPU_GET(cpuid)] = irq;
857#endif
858	if ((gi->gi_flags & GI_FLAG_EARLY_EOI) == GI_FLAG_EARLY_EOI)
859		gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
860
861	if (intr_isrc_dispatch(&gi->gi_isrc, tf) != 0) {
862		gic_irq_mask(sc, irq);
863		if ((gi->gi_flags & GI_FLAG_EARLY_EOI) != GI_FLAG_EARLY_EOI)
864			gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
865		device_printf(sc->gic_dev, "Stray irq %u disabled\n", irq);
866	}
867
868next_irq:
869	arm_irq_memory_barrier(irq);
870	irq_active_reg = gic_c_read_4(sc, GICC_IAR);
871	irq = irq_active_reg & 0x3FF;
872	if (irq < sc->nirqs)
873		goto dispatch_irq;
874
875	return (FILTER_HANDLED);
876}
877
878static void
879gic_config(struct arm_gic_softc *sc, u_int irq, enum intr_trigger trig,
880    enum intr_polarity pol)
881{
882	uint32_t reg;
883	uint32_t mask;
884
885	if (irq < GIC_FIRST_SPI)
886		return;
887
888	mtx_lock_spin(&sc->mutex);
889
890	reg = gic_d_read_4(sc, GICD_ICFGR(irq >> 4));
891	mask = (reg >> 2*(irq % 16)) & 0x3;
892
893	if (pol == INTR_POLARITY_LOW) {
894		mask &= ~GICD_ICFGR_POL_MASK;
895		mask |= GICD_ICFGR_POL_LOW;
896	} else if (pol == INTR_POLARITY_HIGH) {
897		mask &= ~GICD_ICFGR_POL_MASK;
898		mask |= GICD_ICFGR_POL_HIGH;
899	}
900
901	if (trig == INTR_TRIGGER_LEVEL) {
902		mask &= ~GICD_ICFGR_TRIG_MASK;
903		mask |= GICD_ICFGR_TRIG_LVL;
904	} else if (trig == INTR_TRIGGER_EDGE) {
905		mask &= ~GICD_ICFGR_TRIG_MASK;
906		mask |= GICD_ICFGR_TRIG_EDGE;
907	}
908
909	/* Set mask */
910	reg = reg & ~(0x3 << 2*(irq % 16));
911	reg = reg | (mask << 2*(irq % 16));
912	gic_d_write_4(sc, GICD_ICFGR(irq >> 4), reg);
913
914	mtx_unlock_spin(&sc->mutex);
915}
916
917static int
918gic_bind(struct arm_gic_softc *sc, u_int irq, cpuset_t *cpus)
919{
920	uint32_t cpu, end, mask;
921
922	end = min(mp_ncpus, 8);
923	for (cpu = end; cpu < MAXCPU; cpu++)
924		if (CPU_ISSET(cpu, cpus))
925			return (EINVAL);
926
927	for (mask = 0, cpu = 0; cpu < end; cpu++)
928		if (CPU_ISSET(cpu, cpus))
929			mask |= 1 << cpu;
930
931	gic_d_write_1(sc, GICD_ITARGETSR(0) + irq, mask);
932	return (0);
933}
934
935#ifdef FDT
936static int
937gic_map_fdt(device_t dev, u_int ncells, pcell_t *cells, u_int *irqp,
938    enum intr_polarity *polp, enum intr_trigger *trigp)
939{
940
941	if (ncells == 1) {
942		*irqp = cells[0];
943		*polp = INTR_POLARITY_CONFORM;
944		*trigp = INTR_TRIGGER_CONFORM;
945		return (0);
946	}
947	if (ncells == 3) {
948		u_int irq, tripol;
949
950		/*
951		 * The 1st cell is the interrupt type:
952		 *	0 = SPI
953		 *	1 = PPI
954		 * The 2nd cell contains the interrupt number:
955		 *	[0 - 987] for SPI
956		 *	[0 -  15] for PPI
957		 * The 3rd cell is the flags, encoded as follows:
958		 *   bits[3:0] trigger type and level flags
959		 *	1 = low-to-high edge triggered
960		 *	2 = high-to-low edge triggered
961		 *	4 = active high level-sensitive
962		 *	8 = active low level-sensitive
963		 *   bits[15:8] PPI interrupt cpu mask
964		 *	Each bit corresponds to each of the 8 possible cpus
965		 *	attached to the GIC.  A bit set to '1' indicated
966		 *	the interrupt is wired to that CPU.
967		 */
968		switch (cells[0]) {
969		case 0:
970			irq = GIC_FIRST_SPI + cells[1];
971			/* SPI irq is checked later. */
972			break;
973		case 1:
974			irq = GIC_FIRST_PPI + cells[1];
975			if (irq > GIC_LAST_PPI) {
976				device_printf(dev, "unsupported PPI interrupt "
977				    "number %u\n", cells[1]);
978				return (EINVAL);
979			}
980			break;
981		default:
982			device_printf(dev, "unsupported interrupt type "
983			    "configuration %u\n", cells[0]);
984			return (EINVAL);
985		}
986
987		tripol = cells[2] & 0xff;
988		if (tripol & 0xf0 || (tripol & 0x0a && cells[0] == 0))
989			device_printf(dev, "unsupported trigger/polarity "
990			    "configuration 0x%02x\n", tripol);
991
992		*irqp = irq;
993		*polp = INTR_POLARITY_CONFORM;
994		*trigp = tripol & 0x03 ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL;
995		return (0);
996	}
997	return (EINVAL);
998}
999#endif
1000
1001static int
1002gic_map_intr(device_t dev, struct intr_map_data *data, u_int *irqp,
1003    enum intr_polarity *polp, enum intr_trigger *trigp)
1004{
1005	u_int irq;
1006	enum intr_polarity pol;
1007	enum intr_trigger trig;
1008	struct arm_gic_softc *sc;
1009#ifdef FDT
1010	struct intr_map_data_fdt *daf;
1011#endif
1012
1013	sc = device_get_softc(dev);
1014	switch (data->type) {
1015#ifdef FDT
1016	case INTR_MAP_DATA_FDT:
1017		daf = (struct intr_map_data_fdt *)data;
1018		if (gic_map_fdt(dev, daf->ncells, daf->cells, &irq, &pol,
1019		    &trig) != 0)
1020			return (EINVAL);
1021		break;
1022#endif
1023	default:
1024		return (ENOTSUP);
1025	}
1026
1027	if (irq >= sc->nirqs)
1028		return (EINVAL);
1029	if (pol != INTR_POLARITY_CONFORM && pol != INTR_POLARITY_LOW &&
1030	    pol != INTR_POLARITY_HIGH)
1031		return (EINVAL);
1032	if (trig != INTR_TRIGGER_CONFORM && trig != INTR_TRIGGER_EDGE &&
1033	    trig != INTR_TRIGGER_LEVEL)
1034		return (EINVAL);
1035
1036	*irqp = irq;
1037	if (polp != NULL)
1038		*polp = pol;
1039	if (trigp != NULL)
1040		*trigp = trig;
1041	return (0);
1042}
1043
1044static int
1045arm_gic_map_intr(device_t dev, struct intr_map_data *data,
1046    struct intr_irqsrc **isrcp)
1047{
1048	int error;
1049	u_int irq;
1050	struct arm_gic_softc *sc;
1051
1052	error = gic_map_intr(dev, data, &irq, NULL, NULL);
1053	if (error == 0) {
1054		sc = device_get_softc(dev);
1055		*isrcp = GIC_INTR_ISRC(sc, irq);
1056	}
1057	return (error);
1058}
1059
1060static int
1061arm_gic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
1062    struct resource *res, struct intr_map_data *data)
1063{
1064	struct arm_gic_softc *sc = device_get_softc(dev);
1065	struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
1066	u_int irq;
1067	enum intr_trigger trig;
1068	enum intr_polarity pol;
1069
1070	if (data == NULL)
1071		return (ENOTSUP);
1072
1073	/* Get config for resource. */
1074	if (gic_map_intr(dev, data, &irq, &pol, &trig))
1075		return (EINVAL);
1076
1077	if (gi->gi_irq != irq)
1078		return (EINVAL);
1079
1080	/* Compare config if this is not first setup. */
1081	if (isrc->isrc_handlers != 0) {
1082		if ((pol != INTR_POLARITY_CONFORM && pol != gi->gi_pol) ||
1083		    (trig != INTR_TRIGGER_CONFORM && trig != gi->gi_trig))
1084			return (EINVAL);
1085		else
1086			return (0);
1087	}
1088
1089	if (pol == INTR_POLARITY_CONFORM)
1090		pol = INTR_POLARITY_LOW;	/* just pick some */
1091	if (trig == INTR_TRIGGER_CONFORM)
1092		trig = INTR_TRIGGER_EDGE;	/* just pick some */
1093
1094	gi->gi_pol = pol;
1095	gi->gi_trig = trig;
1096	/* Edge triggered interrupts need an early EOI sent */
1097	if (gi->gi_pol == INTR_TRIGGER_EDGE)
1098		gi->gi_flags |= GI_FLAG_EARLY_EOI;
1099
1100	/*
1101	 * XXX - In case that per CPU interrupt is going to be enabled in time
1102	 *       when SMP is already started, we need some IPI call which
1103	 *       enables it on others CPUs. Further, it's more complicated as
1104	 *       pic_enable_source() and pic_disable_source() should act on
1105	 *       per CPU basis only. Thus, it should be solved here somehow.
1106	 */
1107	if (isrc->isrc_flags & INTR_ISRCF_PPI)
1108		CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
1109
1110	gic_config(sc, gi->gi_irq, trig, pol);
1111	arm_gic_bind_intr(dev, isrc);
1112	return (0);
1113}
1114
1115static int
1116arm_gic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
1117    struct resource *res, struct intr_map_data *data)
1118{
1119	struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
1120
1121	if (isrc->isrc_handlers == 0) {
1122		gi->gi_pol = INTR_POLARITY_CONFORM;
1123		gi->gi_trig = INTR_TRIGGER_CONFORM;
1124	}
1125	return (0);
1126}
1127
1128static void
1129arm_gic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
1130{
1131	struct arm_gic_softc *sc = device_get_softc(dev);
1132	struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
1133
1134	arm_irq_memory_barrier(gi->gi_irq);
1135	gic_irq_unmask(sc, gi->gi_irq);
1136}
1137
1138static void
1139arm_gic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
1140{
1141	struct arm_gic_softc *sc = device_get_softc(dev);
1142	struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
1143
1144	gic_irq_mask(sc, gi->gi_irq);
1145}
1146
1147static void
1148arm_gic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
1149{
1150	struct arm_gic_softc *sc = device_get_softc(dev);
1151	struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
1152
1153	arm_gic_disable_intr(dev, isrc);
1154	gic_c_write_4(sc, GICC_EOIR, gi->gi_irq);
1155}
1156
1157static void
1158arm_gic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
1159{
1160
1161	arm_irq_memory_barrier(0);
1162	arm_gic_enable_intr(dev, isrc);
1163}
1164
1165static void
1166arm_gic_post_filter(device_t dev, struct intr_irqsrc *isrc)
1167{
1168	struct arm_gic_softc *sc = device_get_softc(dev);
1169	struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
1170
1171        /* EOI for edge-triggered done earlier. */
1172	if ((gi->gi_flags & GI_FLAG_EARLY_EOI) == GI_FLAG_EARLY_EOI)
1173		return;
1174
1175	arm_irq_memory_barrier(0);
1176	gic_c_write_4(sc, GICC_EOIR, gi->gi_irq);
1177}
1178
1179static int
1180arm_gic_bind_intr(device_t dev, struct intr_irqsrc *isrc)
1181{
1182	struct arm_gic_softc *sc = device_get_softc(dev);
1183	struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
1184
1185	if (gi->gi_irq < GIC_FIRST_SPI)
1186		return (EINVAL);
1187
1188	if (CPU_EMPTY(&isrc->isrc_cpu)) {
1189		gic_irq_cpu = intr_irq_next_cpu(gic_irq_cpu, &all_cpus);
1190		CPU_SETOF(gic_irq_cpu, &isrc->isrc_cpu);
1191	}
1192	return (gic_bind(sc, gi->gi_irq, &isrc->isrc_cpu));
1193}
1194
1195#ifdef SMP
1196static void
1197arm_gic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus,
1198    u_int ipi)
1199{
1200	struct arm_gic_softc *sc = device_get_softc(dev);
1201	struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
1202	uint32_t val = 0, i;
1203
1204	for (i = 0; i < MAXCPU; i++)
1205		if (CPU_ISSET(i, &cpus))
1206			val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT;
1207
1208	gic_d_write_4(sc, GICD_SGIR(0), val | gi->gi_irq);
1209}
1210
1211static int
1212arm_gic_ipi_setup(device_t dev, u_int ipi, struct intr_irqsrc **isrcp)
1213{
1214	struct intr_irqsrc *isrc;
1215	struct arm_gic_softc *sc = device_get_softc(dev);
1216
1217	if (sgi_first_unused > GIC_LAST_SGI)
1218		return (ENOSPC);
1219
1220	isrc = GIC_INTR_ISRC(sc, sgi_first_unused);
1221	sgi_to_ipi[sgi_first_unused++] = ipi;
1222
1223	CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
1224
1225	*isrcp = isrc;
1226	return (0);
1227}
1228#endif
1229#else
1230static int
1231arm_gic_next_irq(struct arm_gic_softc *sc, int last_irq)
1232{
1233	uint32_t active_irq;
1234
1235	active_irq = gic_c_read_4(sc, GICC_IAR);
1236
1237	/*
1238	 * Immediately EOIR the SGIs, because doing so requires the other
1239	 * bits (ie CPU number), not just the IRQ number, and we do not
1240	 * have this information later.
1241	 */
1242	if ((active_irq & 0x3ff) <= GIC_LAST_SGI)
1243		gic_c_write_4(sc, GICC_EOIR, active_irq);
1244	active_irq &= 0x3FF;
1245
1246	if (active_irq == 0x3FF) {
1247		if (last_irq == -1)
1248			device_printf(sc->gic_dev,
1249			    "Spurious interrupt detected\n");
1250		return -1;
1251	}
1252
1253	return active_irq;
1254}
1255
1256static int
1257arm_gic_config(device_t dev, int irq, enum intr_trigger trig,
1258    enum intr_polarity pol)
1259{
1260	struct arm_gic_softc *sc = device_get_softc(dev);
1261	uint32_t reg;
1262	uint32_t mask;
1263
1264	/* Function is public-accessible, so validate input arguments */
1265	if ((irq < 0) || (irq >= sc->nirqs))
1266		goto invalid_args;
1267	if ((trig != INTR_TRIGGER_EDGE) && (trig != INTR_TRIGGER_LEVEL) &&
1268	    (trig != INTR_TRIGGER_CONFORM))
1269		goto invalid_args;
1270	if ((pol != INTR_POLARITY_HIGH) && (pol != INTR_POLARITY_LOW) &&
1271	    (pol != INTR_POLARITY_CONFORM))
1272		goto invalid_args;
1273
1274	mtx_lock_spin(&sc->mutex);
1275
1276	reg = gic_d_read_4(sc, GICD_ICFGR(irq >> 4));
1277	mask = (reg >> 2*(irq % 16)) & 0x3;
1278
1279	if (pol == INTR_POLARITY_LOW) {
1280		mask &= ~GICD_ICFGR_POL_MASK;
1281		mask |= GICD_ICFGR_POL_LOW;
1282	} else if (pol == INTR_POLARITY_HIGH) {
1283		mask &= ~GICD_ICFGR_POL_MASK;
1284		mask |= GICD_ICFGR_POL_HIGH;
1285	}
1286
1287	if (trig == INTR_TRIGGER_LEVEL) {
1288		mask &= ~GICD_ICFGR_TRIG_MASK;
1289		mask |= GICD_ICFGR_TRIG_LVL;
1290	} else if (trig == INTR_TRIGGER_EDGE) {
1291		mask &= ~GICD_ICFGR_TRIG_MASK;
1292		mask |= GICD_ICFGR_TRIG_EDGE;
1293	}
1294
1295	/* Set mask */
1296	reg = reg & ~(0x3 << 2*(irq % 16));
1297	reg = reg | (mask << 2*(irq % 16));
1298	gic_d_write_4(sc, GICD_ICFGR(irq >> 4), reg);
1299
1300	mtx_unlock_spin(&sc->mutex);
1301
1302	return (0);
1303
1304invalid_args:
1305	device_printf(dev, "gic_config_irg, invalid parameters\n");
1306	return (EINVAL);
1307}
1308
1309
1310static void
1311arm_gic_mask(device_t dev, int irq)
1312{
1313	struct arm_gic_softc *sc = device_get_softc(dev);
1314
1315	gic_d_write_4(sc, GICD_ICENABLER(irq >> 5), (1UL << (irq & 0x1F)));
1316	gic_c_write_4(sc, GICC_EOIR, irq); /* XXX - not allowed */
1317}
1318
1319static void
1320arm_gic_unmask(device_t dev, int irq)
1321{
1322	struct arm_gic_softc *sc = device_get_softc(dev);
1323
1324	if (irq > GIC_LAST_SGI)
1325		arm_irq_memory_barrier(irq);
1326
1327	gic_d_write_4(sc, GICD_ISENABLER(irq >> 5), (1UL << (irq & 0x1F)));
1328}
1329
1330#ifdef SMP
1331static void
1332arm_gic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi)
1333{
1334	struct arm_gic_softc *sc = device_get_softc(dev);
1335	uint32_t val = 0, i;
1336
1337	for (i = 0; i < MAXCPU; i++)
1338		if (CPU_ISSET(i, &cpus))
1339			val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT;
1340
1341	gic_d_write_4(sc, GICD_SGIR(0), val | ipi);
1342}
1343
1344static int
1345arm_gic_ipi_read(device_t dev, int i)
1346{
1347
1348	if (i != -1) {
1349		/*
1350		 * The intr code will automagically give the frame pointer
1351		 * if the interrupt argument is 0.
1352		 */
1353		if ((unsigned int)i > 16)
1354			return (0);
1355		return (i);
1356	}
1357
1358	return (0x3ff);
1359}
1360
1361static void
1362arm_gic_ipi_clear(device_t dev, int ipi)
1363{
1364	/* no-op */
1365}
1366#endif
1367
1368static void
1369gic_post_filter(void *arg)
1370{
1371	struct arm_gic_softc *sc = gic_sc;
1372	uintptr_t irq = (uintptr_t) arg;
1373
1374	if (irq > GIC_LAST_SGI)
1375		arm_irq_memory_barrier(irq);
1376	gic_c_write_4(sc, GICC_EOIR, irq);
1377}
1378
1379static int
1380gic_config_irq(int irq, enum intr_trigger trig, enum intr_polarity pol)
1381{
1382
1383	return (arm_gic_config(gic_sc->gic_dev, irq, trig, pol));
1384}
1385
1386void
1387arm_mask_irq(uintptr_t nb)
1388{
1389
1390	arm_gic_mask(gic_sc->gic_dev, nb);
1391}
1392
1393void
1394arm_unmask_irq(uintptr_t nb)
1395{
1396
1397	arm_gic_unmask(gic_sc->gic_dev, nb);
1398}
1399
1400int
1401arm_get_next_irq(int last_irq)
1402{
1403
1404	return (arm_gic_next_irq(gic_sc, last_irq));
1405}
1406
1407#ifdef SMP
1408void
1409intr_pic_init_secondary(void)
1410{
1411
1412	arm_gic_init_secondary(gic_sc->gic_dev);
1413}
1414
1415void
1416pic_ipi_send(cpuset_t cpus, u_int ipi)
1417{
1418
1419	arm_gic_ipi_send(gic_sc->gic_dev, cpus, ipi);
1420}
1421
1422int
1423pic_ipi_read(int i)
1424{
1425
1426	return (arm_gic_ipi_read(gic_sc->gic_dev, i));
1427}
1428
1429void
1430pic_ipi_clear(int ipi)
1431{
1432
1433	arm_gic_ipi_clear(gic_sc->gic_dev, ipi);
1434}
1435#endif
1436#endif /* INTRNG */
1437
1438static device_method_t arm_gic_methods[] = {
1439	/* Device interface */
1440	DEVMETHOD(device_probe,		arm_gic_probe),
1441	DEVMETHOD(device_attach,	arm_gic_attach),
1442
1443#ifdef INTRNG
1444	/* Bus interface */
1445	DEVMETHOD(bus_add_child,	bus_generic_add_child),
1446	DEVMETHOD(bus_alloc_resource,	arm_gic_alloc_resource),
1447	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
1448	DEVMETHOD(bus_activate_resource,bus_generic_activate_resource),
1449
1450	/* ofw_bus interface */
1451	DEVMETHOD(ofw_bus_get_devinfo,	arm_gic_ofw_get_devinfo),
1452	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
1453	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
1454	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
1455	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
1456	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
1457
1458	/* Interrupt controller interface */
1459	DEVMETHOD(pic_disable_intr,	arm_gic_disable_intr),
1460	DEVMETHOD(pic_enable_intr,	arm_gic_enable_intr),
1461	DEVMETHOD(pic_map_intr,		arm_gic_map_intr),
1462	DEVMETHOD(pic_setup_intr,	arm_gic_setup_intr),
1463	DEVMETHOD(pic_teardown_intr,	arm_gic_teardown_intr),
1464	DEVMETHOD(pic_post_filter,	arm_gic_post_filter),
1465	DEVMETHOD(pic_post_ithread,	arm_gic_post_ithread),
1466	DEVMETHOD(pic_pre_ithread,	arm_gic_pre_ithread),
1467#ifdef SMP
1468	DEVMETHOD(pic_bind_intr,	arm_gic_bind_intr),
1469	DEVMETHOD(pic_init_secondary,	arm_gic_init_secondary),
1470	DEVMETHOD(pic_ipi_send,		arm_gic_ipi_send),
1471	DEVMETHOD(pic_ipi_setup,	arm_gic_ipi_setup),
1472#endif
1473#endif
1474	{ 0, 0 }
1475};
1476
1477static driver_t arm_gic_driver = {
1478	"gic",
1479	arm_gic_methods,
1480	sizeof(struct arm_gic_softc),
1481};
1482
1483static devclass_t arm_gic_devclass;
1484
1485EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0,
1486    BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
1487EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0,
1488    BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
1489
1490#ifdef INTRNG
1491/*
1492 * GICv2m support -- the GICv2 MSI/MSI-X controller.
1493 */
1494
1495#define	GICV2M_MSI_TYPER	0x008
1496#define	 MSI_TYPER_SPI_BASE(x)	(((x) >> 16) & 0x3ff)
1497#define	 MSI_TYPER_SPI_COUNT(x)	(((x) >> 0) & 0x3ff)
1498#define	GICv2M_MSI_SETSPI_NS	0x040
1499#define	GICV2M_MSI_IIDR		0xFCC
1500
1501struct arm_gicv2m_softc {
1502	struct resource	*sc_mem;
1503	struct mtx	sc_mutex;
1504	u_int		sc_spi_start;
1505	u_int		sc_spi_count;
1506	u_int		sc_spi_offset;
1507};
1508
1509static struct ofw_compat_data gicv2m_compat_data[] = {
1510	{"arm,gic-v2m-frame",	true},
1511	{NULL,			false}
1512};
1513
1514static int
1515arm_gicv2m_probe(device_t dev)
1516{
1517
1518	if (!ofw_bus_status_okay(dev))
1519		return (ENXIO);
1520
1521	if (!ofw_bus_search_compatible(dev, gicv2m_compat_data)->ocd_data)
1522		return (ENXIO);
1523
1524	device_set_desc(dev, "ARM Generic Interrupt Controller MSI/MSIX");
1525	return (BUS_PROBE_DEFAULT);
1526}
1527
1528static int
1529arm_gicv2m_attach(device_t dev)
1530{
1531	struct arm_gicv2m_softc *sc;
1532	uint32_t typer;
1533	int rid;
1534
1535	sc = device_get_softc(dev);
1536
1537	rid = 0;
1538	sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
1539	    RF_ACTIVE);
1540	if (sc->sc_mem == NULL) {
1541		device_printf(dev, "Unable to allocate resources\n");
1542		return (ENXIO);
1543	}
1544
1545	typer = bus_read_4(sc->sc_mem, GICV2M_MSI_TYPER);
1546	sc->sc_spi_start = MSI_TYPER_SPI_BASE(typer);
1547	sc->sc_spi_count = MSI_TYPER_SPI_COUNT(typer);
1548
1549	mtx_init(&sc->sc_mutex, "GICv2m lock", "", MTX_DEF);
1550
1551	if (bootverbose)
1552		device_printf(dev, "using spi %u to %u\n", sc->sc_spi_start,
1553		    sc->sc_spi_start + sc->sc_spi_count - 1);
1554
1555	return (0);
1556}
1557
1558static device_method_t arm_gicv2m_methods[] = {
1559	/* Device interface */
1560	DEVMETHOD(device_probe,		arm_gicv2m_probe),
1561	DEVMETHOD(device_attach,	arm_gicv2m_attach),
1562
1563	/* End */
1564	DEVMETHOD_END
1565};
1566
1567DEFINE_CLASS_0(gicv2m, arm_gicv2m_driver, arm_gicv2m_methods,
1568    sizeof(struct arm_gicv2m_softc));
1569
1570static devclass_t arm_gicv2m_devclass;
1571
1572EARLY_DRIVER_MODULE(gicv2m, gic, arm_gicv2m_driver,
1573    arm_gicv2m_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
1574#endif
1575