xref: /freebsd/sys/powerpc/powerpc/openpic.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
160727d8bSWarner Losh /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
371e3c308SPedro F. Giffuni  *
4ca019208SBenno Rice  * Copyright (C) 2002 Benno Rice.
5ca019208SBenno Rice  * All rights reserved.
6ca019208SBenno Rice  *
7ca019208SBenno Rice  * Redistribution and use in source and binary forms, with or without
8ca019208SBenno Rice  * modification, are permitted provided that the following conditions
9ca019208SBenno Rice  * are met:
10ca019208SBenno Rice  * 1. Redistributions of source code must retain the above copyright
11ca019208SBenno Rice  *    notice, this list of conditions and the following disclaimer.
12ca019208SBenno Rice  * 2. Redistributions in binary form must reproduce the above copyright
13ca019208SBenno Rice  *    notice, this list of conditions and the following disclaimer in the
14ca019208SBenno Rice  *    documentation and/or other materials provided with the distribution.
15ca019208SBenno Rice  *
16ca019208SBenno Rice  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
17ca019208SBenno Rice  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18ca019208SBenno Rice  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19ca019208SBenno Rice  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20ca019208SBenno Rice  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21ca019208SBenno Rice  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22ca019208SBenno Rice  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23ca019208SBenno Rice  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24ca019208SBenno Rice  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25ca019208SBenno Rice  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26ca019208SBenno Rice  */
27ca019208SBenno Rice 
28ca019208SBenno Rice #include <sys/param.h>
29ca019208SBenno Rice #include <sys/systm.h>
30ca019208SBenno Rice #include <sys/bus.h>
31ca019208SBenno Rice #include <sys/conf.h>
32ca019208SBenno Rice #include <sys/kernel.h>
33e2e050c8SConrad Meyer #include <sys/ktr.h>
3408393b3eSNathan Whitehorn #include <sys/proc.h>
3577d40ffdSMarcel Moolenaar #include <sys/rman.h>
3608393b3eSNathan Whitehorn #include <sys/sched.h>
374290b4b8SJustin Hibbits #include <sys/smp.h>
38ca019208SBenno Rice 
39ca019208SBenno Rice #include <machine/bus.h>
40ca019208SBenno Rice #include <machine/intr_machdep.h>
41ca019208SBenno Rice #include <machine/md_var.h>
42ca019208SBenno Rice #include <machine/pio.h>
43ca019208SBenno Rice #include <machine/resource.h>
44ca019208SBenno Rice 
45ca019208SBenno Rice #include <vm/vm.h>
46ca019208SBenno Rice #include <vm/pmap.h>
47ca019208SBenno Rice 
48ca019208SBenno Rice #include <machine/openpicreg.h>
49ca019208SBenno Rice #include <machine/openpicvar.h>
50ca019208SBenno Rice 
51ca019208SBenno Rice #include "pic_if.h"
52ca019208SBenno Rice 
539e2b2d69SJustin Hibbits #define	OPENPIC_NIPIS		4
549e2b2d69SJustin Hibbits 
55ca019208SBenno Rice /*
56ca019208SBenno Rice  * Local routines
57ca019208SBenno Rice  */
58eaef5f0aSNathan Whitehorn static int openpic_intr(void *arg);
59739af9bcSPeter Grehan 
6077d40ffdSMarcel Moolenaar static __inline uint32_t
openpic_read(struct openpic_softc * sc,u_int reg)6177d40ffdSMarcel Moolenaar openpic_read(struct openpic_softc *sc, u_int reg)
62ca019208SBenno Rice {
6377d40ffdSMarcel Moolenaar 	return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg));
646f1808faSPeter Grehan }
656f1808faSPeter Grehan 
6677d40ffdSMarcel Moolenaar static __inline void
openpic_write(struct openpic_softc * sc,u_int reg,uint32_t val)6777d40ffdSMarcel Moolenaar openpic_write(struct openpic_softc *sc, u_int reg, uint32_t val)
6877d40ffdSMarcel Moolenaar {
6977d40ffdSMarcel Moolenaar 	bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val);
7077d40ffdSMarcel Moolenaar }
71ca019208SBenno Rice 
72739af9bcSPeter Grehan int
openpic_common_attach(device_t dev,uint32_t node)736d2d7b8cSMarcel Moolenaar openpic_common_attach(device_t dev, uint32_t node)
74739af9bcSPeter Grehan {
75739af9bcSPeter Grehan 	struct openpic_softc *sc;
7612640815SMarcel Moolenaar 	u_int     cpu, ipi, irq;
77739af9bcSPeter Grehan 	u_int32_t x;
78739af9bcSPeter Grehan 
79739af9bcSPeter Grehan 	sc = device_get_softc(dev);
8077d40ffdSMarcel Moolenaar 	sc->sc_dev = dev;
81739af9bcSPeter Grehan 
8277d40ffdSMarcel Moolenaar 	sc->sc_rid = 0;
8377d40ffdSMarcel Moolenaar 	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
8477d40ffdSMarcel Moolenaar 	    RF_ACTIVE);
8577d40ffdSMarcel Moolenaar 
8677d40ffdSMarcel Moolenaar 	if (sc->sc_memr == NULL) {
8777d40ffdSMarcel Moolenaar 		device_printf(dev, "Could not alloc mem resource!\n");
8877d40ffdSMarcel Moolenaar 		return (ENXIO);
8977d40ffdSMarcel Moolenaar 	}
9077d40ffdSMarcel Moolenaar 
9177d40ffdSMarcel Moolenaar 	sc->sc_bt = rman_get_bustag(sc->sc_memr);
9277d40ffdSMarcel Moolenaar 	sc->sc_bh = rman_get_bushandle(sc->sc_memr);
93739af9bcSPeter Grehan 
94ca2c1931SNathan Whitehorn 	/* Reset the PIC */
95ca2c1931SNathan Whitehorn 	x = openpic_read(sc, OPENPIC_CONFIG);
96ca2c1931SNathan Whitehorn 	x |= OPENPIC_CONFIG_RESET;
97ca2c1931SNathan Whitehorn 	openpic_write(sc, OPENPIC_CONFIG, x);
98ca2c1931SNathan Whitehorn 
99ca2c1931SNathan Whitehorn 	while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) {
100ca2c1931SNathan Whitehorn 		powerpc_sync();
101ca2c1931SNathan Whitehorn 		DELAY(100);
102ca2c1931SNathan Whitehorn 	}
103ca2c1931SNathan Whitehorn 
104eaef5f0aSNathan Whitehorn 	/* Check if this is a cascaded PIC */
105eaef5f0aSNathan Whitehorn 	sc->sc_irq = 0;
106eaef5f0aSNathan Whitehorn 	sc->sc_intr = NULL;
107bd077006SMarcel Moolenaar 	do {
108bd077006SMarcel Moolenaar 		struct resource_list *rl;
109bd077006SMarcel Moolenaar 
110bd077006SMarcel Moolenaar 		rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
111bd077006SMarcel Moolenaar 		if (rl == NULL)
112bd077006SMarcel Moolenaar 			break;
113bd077006SMarcel Moolenaar 		if (resource_list_find(rl, SYS_RES_IRQ, 0) == NULL)
114bd077006SMarcel Moolenaar 			break;
115bd077006SMarcel Moolenaar 
116eaef5f0aSNathan Whitehorn 		sc->sc_intr = bus_alloc_resource_any(dev, SYS_RES_IRQ,
117eaef5f0aSNathan Whitehorn 		    &sc->sc_irq, RF_ACTIVE);
118eaef5f0aSNathan Whitehorn 
119eaef5f0aSNathan Whitehorn 		/* XXX Cascaded PICs pass NULL trapframes! */
120eaef5f0aSNathan Whitehorn 		bus_setup_intr(dev, sc->sc_intr, INTR_TYPE_MISC | INTR_MPSAFE,
121eaef5f0aSNathan Whitehorn 		    openpic_intr, NULL, dev, &sc->sc_icookie);
122bd077006SMarcel Moolenaar 	} while (0);
123eaef5f0aSNathan Whitehorn 
124eaef5f0aSNathan Whitehorn 	/* Reset the PIC */
125eaef5f0aSNathan Whitehorn 	x = openpic_read(sc, OPENPIC_CONFIG);
126eaef5f0aSNathan Whitehorn 	x |= OPENPIC_CONFIG_RESET;
127eaef5f0aSNathan Whitehorn 	openpic_write(sc, OPENPIC_CONFIG, x);
128eaef5f0aSNathan Whitehorn 
129eaef5f0aSNathan Whitehorn 	while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) {
130eaef5f0aSNathan Whitehorn 		powerpc_sync();
131eaef5f0aSNathan Whitehorn 		DELAY(100);
132eaef5f0aSNathan Whitehorn 	}
133eaef5f0aSNathan Whitehorn 
134739af9bcSPeter Grehan 	x = openpic_read(sc, OPENPIC_FEATURE);
135739af9bcSPeter Grehan 	switch (x & OPENPIC_FEATURE_VERSION_MASK) {
136ca019208SBenno Rice 	case 1:
137ca019208SBenno Rice 		sc->sc_version = "1.0";
138ca019208SBenno Rice 		break;
139ca019208SBenno Rice 	case 2:
140ca019208SBenno Rice 		sc->sc_version = "1.2";
141ca019208SBenno Rice 		break;
142ca019208SBenno Rice 	case 3:
143ca019208SBenno Rice 		sc->sc_version = "1.3";
144ca019208SBenno Rice 		break;
145ca019208SBenno Rice 	default:
146ca019208SBenno Rice 		sc->sc_version = "unknown";
147ca019208SBenno Rice 		break;
148ca019208SBenno Rice 	}
149ca019208SBenno Rice 
150739af9bcSPeter Grehan 	sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >>
151cefa2c2cSBenno Rice 	    OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1;
152739af9bcSPeter Grehan 	sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >>
153cefa2c2cSBenno Rice 	    OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1;
154ca019208SBenno Rice 
1559ec28141SPeter Grehan 	/*
156f61afb44SPeter Grehan 	 * PSIM seems to report 1 too many IRQs and CPUs
1579ec28141SPeter Grehan 	 */
158f61afb44SPeter Grehan 	if (sc->sc_psim) {
1599ec28141SPeter Grehan 		sc->sc_nirq--;
160f61afb44SPeter Grehan 		sc->sc_ncpu--;
161f61afb44SPeter Grehan 	}
1629ec28141SPeter Grehan 
163739af9bcSPeter Grehan 	if (bootverbose)
164ca019208SBenno Rice 		device_printf(dev,
165cefa2c2cSBenno Rice 		    "Version %s, supports %d CPUs and %d irqs\n",
166cefa2c2cSBenno Rice 		    sc->sc_version, sc->sc_ncpu, sc->sc_nirq);
167ca019208SBenno Rice 
1689e2b2d69SJustin Hibbits 	/*
1699e2b2d69SJustin Hibbits 	 * Allow more IRQs than what the PIC says it handles.  Some Freescale PICs
1709e2b2d69SJustin Hibbits 	 * have MSIs that show up above the PIC's self-described 196 IRQs
1719e2b2d69SJustin Hibbits 	 * (P5020 starts MSI IRQs at 224).
1729e2b2d69SJustin Hibbits 	 */
1739e2b2d69SJustin Hibbits 	if (sc->sc_quirks & OPENPIC_QUIRK_HIDDEN_IRQS)
1749e2b2d69SJustin Hibbits 		sc->sc_nirq = OPENPIC_IRQMAX - OPENPIC_NIPIS;
1759e2b2d69SJustin Hibbits 
17612640815SMarcel Moolenaar 	for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
17712640815SMarcel Moolenaar 		openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 15);
17812640815SMarcel Moolenaar 
17905c62b81SMarcel Moolenaar 	/* Reset and disable all interrupts. */
18005c62b81SMarcel Moolenaar 	for (irq = 0; irq < sc->sc_nirq; irq++) {
18105c62b81SMarcel Moolenaar 		x = irq;                /* irq == vector. */
18205c62b81SMarcel Moolenaar 		x |= OPENPIC_IMASK;
183a7a32004SNathan Whitehorn 		x |= OPENPIC_POLARITY_NEGATIVE;
18405c62b81SMarcel Moolenaar 		x |= OPENPIC_SENSE_LEVEL;
18505c62b81SMarcel Moolenaar 		x |= 8 << OPENPIC_PRIORITY_SHIFT;
18605c62b81SMarcel Moolenaar 		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
18705c62b81SMarcel Moolenaar 	}
188ca019208SBenno Rice 
18905c62b81SMarcel Moolenaar 	/* Reset and disable all IPIs. */
1909e2b2d69SJustin Hibbits 	for (ipi = 0; ipi < OPENPIC_NIPIS; ipi++) {
19105c62b81SMarcel Moolenaar 		x = sc->sc_nirq + ipi;
19205c62b81SMarcel Moolenaar 		x |= OPENPIC_IMASK;
19305c62b81SMarcel Moolenaar 		x |= 15 << OPENPIC_PRIORITY_SHIFT;
19405c62b81SMarcel Moolenaar 		openpic_write(sc, OPENPIC_IPI_VECTOR(ipi), x);
19505c62b81SMarcel Moolenaar 	}
19605c62b81SMarcel Moolenaar 
197ca019208SBenno Rice 	/* we don't need 8259 passthrough mode */
198ca019208SBenno Rice 	x = openpic_read(sc, OPENPIC_CONFIG);
199ca019208SBenno Rice 	x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
200ca019208SBenno Rice 	openpic_write(sc, OPENPIC_CONFIG, x);
201ca019208SBenno Rice 
202ca019208SBenno Rice 	/* send all interrupts to cpu 0 */
203ca019208SBenno Rice 	for (irq = 0; irq < sc->sc_nirq; irq++)
204ca019208SBenno Rice 		openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0);
205ca019208SBenno Rice 
2064dc2f910SNathan Whitehorn 	/* clear all pending interrupts from cpu 0 */
2076f1808faSPeter Grehan 	for (irq = 0; irq < sc->sc_nirq; irq++) {
2084dc2f910SNathan Whitehorn 		(void)openpic_read(sc, OPENPIC_PCPU_IACK(0));
2094dc2f910SNathan Whitehorn 		openpic_write(sc, OPENPIC_PCPU_EOI(0), 0);
210ca019208SBenno Rice 	}
211ca019208SBenno Rice 
212df1a6d51SMarcel Moolenaar 	for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
213df1a6d51SMarcel Moolenaar 		openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 0);
214df1a6d51SMarcel Moolenaar 
2159e2b2d69SJustin Hibbits 	powerpc_register_pic(dev, node, sc->sc_nirq, OPENPIC_NIPIS, FALSE);
216ca019208SBenno Rice 
217eaef5f0aSNathan Whitehorn 	/* If this is not a cascaded PIC, it must be the root PIC */
218eaef5f0aSNathan Whitehorn 	if (sc->sc_intr == NULL)
219eaef5f0aSNathan Whitehorn 		root_pic = dev;
220eaef5f0aSNathan Whitehorn 
221ca019208SBenno Rice 	return (0);
222ca019208SBenno Rice }
223ca019208SBenno Rice 
224ca019208SBenno Rice /*
22577d40ffdSMarcel Moolenaar  * PIC I/F methods
226ca019208SBenno Rice  */
227ca019208SBenno Rice 
22877d40ffdSMarcel Moolenaar void
openpic_bind(device_t dev,u_int irq,cpuset_t cpumask,void ** priv __unused)22956505ec0SJustin Hibbits openpic_bind(device_t dev, u_int irq, cpuset_t cpumask, void **priv __unused)
23008393b3eSNathan Whitehorn {
23108393b3eSNathan Whitehorn 	struct openpic_softc *sc;
2324290b4b8SJustin Hibbits 	uint32_t mask;
23308393b3eSNathan Whitehorn 
23408393b3eSNathan Whitehorn 	/* If we aren't directly connected to the CPU, this won't work */
23508393b3eSNathan Whitehorn 	if (dev != root_pic)
23608393b3eSNathan Whitehorn 		return;
23708393b3eSNathan Whitehorn 
23808393b3eSNathan Whitehorn 	sc = device_get_softc(dev);
239c47dd3dbSAttilio Rao 
240c47dd3dbSAttilio Rao 	/*
241c47dd3dbSAttilio Rao 	 * XXX: openpic_write() is very special and just needs a 32 bits mask.
242c47dd3dbSAttilio Rao 	 * For the moment, just play dirty and get the first half word.
243c47dd3dbSAttilio Rao 	 */
2444290b4b8SJustin Hibbits 	mask = cpumask.__bits[0] & 0xffffffff;
2454290b4b8SJustin Hibbits 	if (sc->sc_quirks & OPENPIC_QUIRK_SINGLE_BIND) {
2464290b4b8SJustin Hibbits 		int i = mftb() % CPU_COUNT(&cpumask);
2474290b4b8SJustin Hibbits 		int cpu, ncpu;
2484290b4b8SJustin Hibbits 
2494290b4b8SJustin Hibbits 		ncpu = 0;
2504290b4b8SJustin Hibbits 		CPU_FOREACH(cpu) {
2514290b4b8SJustin Hibbits 			if (!(mask & (1 << cpu)))
2524290b4b8SJustin Hibbits 				continue;
2534290b4b8SJustin Hibbits 			if (ncpu == i)
2544290b4b8SJustin Hibbits 				break;
2554290b4b8SJustin Hibbits 			ncpu++;
2564290b4b8SJustin Hibbits 		}
2574290b4b8SJustin Hibbits 		mask &= (1 << cpu);
2584290b4b8SJustin Hibbits 	}
2594290b4b8SJustin Hibbits 
2604290b4b8SJustin Hibbits 	openpic_write(sc, OPENPIC_IDEST(irq), mask);
26108393b3eSNathan Whitehorn }
26208393b3eSNathan Whitehorn 
26308393b3eSNathan Whitehorn void
openpic_config(device_t dev,u_int irq,enum intr_trigger trig,enum intr_polarity pol)264d6f59297SMarcel Moolenaar openpic_config(device_t dev, u_int irq, enum intr_trigger trig,
265d6f59297SMarcel Moolenaar     enum intr_polarity pol)
266d6f59297SMarcel Moolenaar {
267d6f59297SMarcel Moolenaar 	struct openpic_softc *sc;
268d6f59297SMarcel Moolenaar 	uint32_t x;
269d6f59297SMarcel Moolenaar 
270d6f59297SMarcel Moolenaar 	sc = device_get_softc(dev);
271d6f59297SMarcel Moolenaar 	x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
272d6f59297SMarcel Moolenaar 	if (pol == INTR_POLARITY_LOW)
273d6f59297SMarcel Moolenaar 		x &= ~OPENPIC_POLARITY_POSITIVE;
274d6f59297SMarcel Moolenaar 	else
275d6f59297SMarcel Moolenaar 		x |= OPENPIC_POLARITY_POSITIVE;
276d6f59297SMarcel Moolenaar 	if (trig == INTR_TRIGGER_EDGE)
277d6f59297SMarcel Moolenaar 		x &= ~OPENPIC_SENSE_LEVEL;
278d6f59297SMarcel Moolenaar 	else
279d6f59297SMarcel Moolenaar 		x |= OPENPIC_SENSE_LEVEL;
280d6f59297SMarcel Moolenaar 	openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
281d6f59297SMarcel Moolenaar }
282d6f59297SMarcel Moolenaar 
283eaef5f0aSNathan Whitehorn static int
openpic_intr(void * arg)284eaef5f0aSNathan Whitehorn openpic_intr(void *arg)
285eaef5f0aSNathan Whitehorn {
286eaef5f0aSNathan Whitehorn 	device_t dev = (device_t)(arg);
287eaef5f0aSNathan Whitehorn 
288eaef5f0aSNathan Whitehorn 	/* XXX Cascaded PICs do not pass non-NULL trapframes! */
289eaef5f0aSNathan Whitehorn 	openpic_dispatch(dev, NULL);
290eaef5f0aSNathan Whitehorn 
291eaef5f0aSNathan Whitehorn 	return (FILTER_HANDLED);
292eaef5f0aSNathan Whitehorn }
293eaef5f0aSNathan Whitehorn 
294d6f59297SMarcel Moolenaar void
openpic_dispatch(device_t dev,struct trapframe * tf)29577d40ffdSMarcel Moolenaar openpic_dispatch(device_t dev, struct trapframe *tf)
296ca019208SBenno Rice {
297ca019208SBenno Rice 	struct openpic_softc *sc;
298df1a6d51SMarcel Moolenaar 	u_int cpuid, vector;
299ca019208SBenno Rice 
30028bb01e5SRafal Jaworowski 	CTR1(KTR_INTR, "%s: got interrupt", __func__);
30128bb01e5SRafal Jaworowski 
3024dc2f910SNathan Whitehorn 	cpuid = (dev == root_pic) ? PCPU_GET(cpuid) : 0;
3034dc2f910SNathan Whitehorn 
304ca019208SBenno Rice 	sc = device_get_softc(dev);
30577d40ffdSMarcel Moolenaar 	while (1) {
306df1a6d51SMarcel Moolenaar 		vector = openpic_read(sc, OPENPIC_PCPU_IACK(cpuid));
30777d40ffdSMarcel Moolenaar 		vector &= OPENPIC_VECTOR_MASK;
30877d40ffdSMarcel Moolenaar 		if (vector == 255)
30977d40ffdSMarcel Moolenaar 			break;
31077d40ffdSMarcel Moolenaar 		powerpc_dispatch_intr(vector, tf);
311ca019208SBenno Rice 	}
312ca019208SBenno Rice }
313ca019208SBenno Rice 
31477d40ffdSMarcel Moolenaar void
openpic_enable(device_t dev,u_int irq,u_int vector,void ** priv __unused)31556505ec0SJustin Hibbits openpic_enable(device_t dev, u_int irq, u_int vector, void **priv __unused)
316ca019208SBenno Rice {
317ca019208SBenno Rice 	struct openpic_softc *sc;
31877d40ffdSMarcel Moolenaar 	uint32_t x;
319ca019208SBenno Rice 
320ca019208SBenno Rice 	sc = device_get_softc(dev);
32105c62b81SMarcel Moolenaar 	if (irq < sc->sc_nirq) {
322ca019208SBenno Rice 		x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
32377d40ffdSMarcel Moolenaar 		x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
32477d40ffdSMarcel Moolenaar 		x |= vector;
325ca019208SBenno Rice 		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
32605c62b81SMarcel Moolenaar 	} else {
32705c62b81SMarcel Moolenaar 		x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
32805c62b81SMarcel Moolenaar 		x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
32905c62b81SMarcel Moolenaar 		x |= vector;
33005c62b81SMarcel Moolenaar 		openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
33105c62b81SMarcel Moolenaar 	}
332ca019208SBenno Rice }
333ca019208SBenno Rice 
33477d40ffdSMarcel Moolenaar void
openpic_eoi(device_t dev,u_int irq __unused,void * priv __unused)33556505ec0SJustin Hibbits openpic_eoi(device_t dev, u_int irq __unused, void *priv __unused)
336ca019208SBenno Rice {
33777d40ffdSMarcel Moolenaar 	struct openpic_softc *sc;
3384dc2f910SNathan Whitehorn 	u_int cpuid;
3394dc2f910SNathan Whitehorn 
3404dc2f910SNathan Whitehorn 	cpuid = (dev == root_pic) ? PCPU_GET(cpuid) : 0;
341ca019208SBenno Rice 
34277d40ffdSMarcel Moolenaar 	sc = device_get_softc(dev);
3434dc2f910SNathan Whitehorn 	openpic_write(sc, OPENPIC_PCPU_EOI(cpuid), 0);
34405c62b81SMarcel Moolenaar }
34505c62b81SMarcel Moolenaar 
34605c62b81SMarcel Moolenaar void
openpic_ipi(device_t dev,u_int cpu)34705c62b81SMarcel Moolenaar openpic_ipi(device_t dev, u_int cpu)
34805c62b81SMarcel Moolenaar {
34905c62b81SMarcel Moolenaar 	struct openpic_softc *sc;
350928f3319SNathan Whitehorn 
351928f3319SNathan Whitehorn 	KASSERT(dev == root_pic, ("Cannot send IPIs from non-root OpenPIC"));
35205c62b81SMarcel Moolenaar 
35305c62b81SMarcel Moolenaar 	sc = device_get_softc(dev);
35408393b3eSNathan Whitehorn 	sched_pin();
355928f3319SNathan Whitehorn 	openpic_write(sc, OPENPIC_PCPU_IPI_DISPATCH(PCPU_GET(cpuid), 0),
35605c62b81SMarcel Moolenaar 	    1u << cpu);
35708393b3eSNathan Whitehorn 	sched_unpin();
35877d40ffdSMarcel Moolenaar }
35977d40ffdSMarcel Moolenaar 
36077d40ffdSMarcel Moolenaar void
openpic_mask(device_t dev,u_int irq,void * priv __unused)36156505ec0SJustin Hibbits openpic_mask(device_t dev, u_int irq, void *priv __unused)
36277d40ffdSMarcel Moolenaar {
36377d40ffdSMarcel Moolenaar 	struct openpic_softc *sc;
36477d40ffdSMarcel Moolenaar 	uint32_t x;
36577d40ffdSMarcel Moolenaar 
36677d40ffdSMarcel Moolenaar 	sc = device_get_softc(dev);
36705c62b81SMarcel Moolenaar 	if (irq < sc->sc_nirq) {
368ca019208SBenno Rice 		x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
369ca019208SBenno Rice 		x |= OPENPIC_IMASK;
370ca019208SBenno Rice 		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
37105c62b81SMarcel Moolenaar 	} else {
37205c62b81SMarcel Moolenaar 		x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
37305c62b81SMarcel Moolenaar 		x |= OPENPIC_IMASK;
37405c62b81SMarcel Moolenaar 		openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
37505c62b81SMarcel Moolenaar 	}
376ca019208SBenno Rice }
377ca019208SBenno Rice 
37877d40ffdSMarcel Moolenaar void
openpic_unmask(device_t dev,u_int irq,void * priv __unused)37956505ec0SJustin Hibbits openpic_unmask(device_t dev, u_int irq, void *priv __unused)
380ca019208SBenno Rice {
381739af9bcSPeter Grehan 	struct openpic_softc *sc;
38277d40ffdSMarcel Moolenaar 	uint32_t x;
383ca019208SBenno Rice 
38477d40ffdSMarcel Moolenaar 	sc = device_get_softc(dev);
38505c62b81SMarcel Moolenaar 	if (irq < sc->sc_nirq) {
38677d40ffdSMarcel Moolenaar 		x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
38777d40ffdSMarcel Moolenaar 		x &= ~OPENPIC_IMASK;
38877d40ffdSMarcel Moolenaar 		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
38905c62b81SMarcel Moolenaar 	} else {
39005c62b81SMarcel Moolenaar 		x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
39105c62b81SMarcel Moolenaar 		x &= ~OPENPIC_IMASK;
39205c62b81SMarcel Moolenaar 		openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
39305c62b81SMarcel Moolenaar 	}
394ca019208SBenno Rice }
3959a2edf01SJustin Hibbits 
3969a2edf01SJustin Hibbits int
openpic_suspend(device_t dev)3979a2edf01SJustin Hibbits openpic_suspend(device_t dev)
3989a2edf01SJustin Hibbits {
3999a2edf01SJustin Hibbits 	struct openpic_softc *sc;
4009a2edf01SJustin Hibbits 	int i;
4019a2edf01SJustin Hibbits 
4029a2edf01SJustin Hibbits 	sc = device_get_softc(dev);
4039a2edf01SJustin Hibbits 
4049a2edf01SJustin Hibbits 	sc->sc_saved_config = bus_read_4(sc->sc_memr, OPENPIC_CONFIG);
4059e2b2d69SJustin Hibbits 	for (i = 0; i < OPENPIC_NIPIS; i++) {
4069a2edf01SJustin Hibbits 		sc->sc_saved_ipis[i] = bus_read_4(sc->sc_memr, OPENPIC_IPI_VECTOR(i));
4079a2edf01SJustin Hibbits 	}
4089a2edf01SJustin Hibbits 
4099a2edf01SJustin Hibbits 	for (i = 0; i < 4; i++) {
4109a2edf01SJustin Hibbits 		sc->sc_saved_prios[i] = bus_read_4(sc->sc_memr, OPENPIC_PCPU_TPR(i));
4119a2edf01SJustin Hibbits 	}
4129a2edf01SJustin Hibbits 
4139a2edf01SJustin Hibbits 	for (i = 0; i < OPENPIC_TIMERS; i++) {
4149a2edf01SJustin Hibbits 		sc->sc_saved_timers[i].tcnt = bus_read_4(sc->sc_memr, OPENPIC_TCNT(i));
4159a2edf01SJustin Hibbits 		sc->sc_saved_timers[i].tbase = bus_read_4(sc->sc_memr, OPENPIC_TBASE(i));
4169a2edf01SJustin Hibbits 		sc->sc_saved_timers[i].tvec = bus_read_4(sc->sc_memr, OPENPIC_TVEC(i));
4179a2edf01SJustin Hibbits 		sc->sc_saved_timers[i].tdst = bus_read_4(sc->sc_memr, OPENPIC_TDST(i));
4189a2edf01SJustin Hibbits 	}
4199a2edf01SJustin Hibbits 
4209a2edf01SJustin Hibbits 	for (i = 0; i < OPENPIC_SRC_VECTOR_COUNT; i++)
4219a2edf01SJustin Hibbits 		sc->sc_saved_vectors[i] =
4229a2edf01SJustin Hibbits 		    bus_read_4(sc->sc_memr, OPENPIC_SRC_VECTOR(i)) & ~OPENPIC_ACTIVITY;
4239a2edf01SJustin Hibbits 
4249a2edf01SJustin Hibbits 	return (0);
4259a2edf01SJustin Hibbits }
4269a2edf01SJustin Hibbits 
4279a2edf01SJustin Hibbits int
openpic_resume(device_t dev)4289a2edf01SJustin Hibbits openpic_resume(device_t dev)
4299a2edf01SJustin Hibbits {
4309a2edf01SJustin Hibbits     	struct openpic_softc *sc;
4319a2edf01SJustin Hibbits     	int i;
4329a2edf01SJustin Hibbits 
4339a2edf01SJustin Hibbits     	sc = device_get_softc(dev);
4349a2edf01SJustin Hibbits 
4359a2edf01SJustin Hibbits 	sc->sc_saved_config = bus_read_4(sc->sc_memr, OPENPIC_CONFIG);
4369e2b2d69SJustin Hibbits 	for (i = 0; i < OPENPIC_NIPIS; i++) {
4379a2edf01SJustin Hibbits 		bus_write_4(sc->sc_memr, OPENPIC_IPI_VECTOR(i), sc->sc_saved_ipis[i]);
4389a2edf01SJustin Hibbits 	}
4399a2edf01SJustin Hibbits 
4409a2edf01SJustin Hibbits 	for (i = 0; i < 4; i++) {
4419a2edf01SJustin Hibbits 		bus_write_4(sc->sc_memr, OPENPIC_PCPU_TPR(i), sc->sc_saved_prios[i]);
4429a2edf01SJustin Hibbits 	}
4439a2edf01SJustin Hibbits 
4449a2edf01SJustin Hibbits 	for (i = 0; i < OPENPIC_TIMERS; i++) {
4459a2edf01SJustin Hibbits 		bus_write_4(sc->sc_memr, OPENPIC_TCNT(i), sc->sc_saved_timers[i].tcnt);
4469a2edf01SJustin Hibbits 		bus_write_4(sc->sc_memr, OPENPIC_TBASE(i), sc->sc_saved_timers[i].tbase);
4479a2edf01SJustin Hibbits 		bus_write_4(sc->sc_memr, OPENPIC_TVEC(i), sc->sc_saved_timers[i].tvec);
4489a2edf01SJustin Hibbits 		bus_write_4(sc->sc_memr, OPENPIC_TDST(i), sc->sc_saved_timers[i].tdst);
4499a2edf01SJustin Hibbits 	}
4509a2edf01SJustin Hibbits 
4519a2edf01SJustin Hibbits 	for (i = 0; i < OPENPIC_SRC_VECTOR_COUNT; i++)
4529a2edf01SJustin Hibbits 		bus_write_4(sc->sc_memr, OPENPIC_SRC_VECTOR(i), sc->sc_saved_vectors[i]);
4539a2edf01SJustin Hibbits 
4549a2edf01SJustin Hibbits 	return (0);
4559a2edf01SJustin Hibbits }
456