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