2 * Copyright (C) 2002 Benno Rice.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/param.h>
29 #include <sys/systm.h>
32 #include <sys/kernel.h>
35 #include <machine/bus.h>
36 #include <machine/intr.h>
37 #include <machine/intr_machdep.h>
38 #include <machine/md_var.h>
39 #include <machine/pio.h>
40 #include <machine/resource.h>
45 #include <machine/openpicreg.h>
46 #include <machine/openpicvar.h>
50 devclass_t openpic_devclass;
56 static __inline uint32_t
57 openpic_read(struct openpic_softc *sc, u_int reg)
59 return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg));
63 openpic_write(struct openpic_softc *sc, u_int reg, uint32_t val)
65 bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val);
69 openpic_set_priority(struct openpic_softc *sc, int pri)
74 tpr = OPENPIC_PCPU_TPR(PCPU_GET(cpuid));
75 x = openpic_read(sc, tpr);
76 x &= ~OPENPIC_TPR_MASK;
78 openpic_write(sc, tpr, x);
82 openpic_attach(device_t dev)
84 struct openpic_softc *sc;
88 sc = device_get_softc(dev);
92 sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
95 if (sc->sc_memr == NULL) {
96 device_printf(dev, "Could not alloc mem resource!\n");
100 sc->sc_bt = rman_get_bustag(sc->sc_memr);
101 sc->sc_bh = rman_get_bushandle(sc->sc_memr);
104 x = openpic_read(sc, OPENPIC_CONFIG);
105 x |= OPENPIC_CONFIG_RESET;
106 openpic_write(sc, OPENPIC_CONFIG, x);
108 while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) {
113 x = openpic_read(sc, OPENPIC_FEATURE);
114 switch (x & OPENPIC_FEATURE_VERSION_MASK) {
116 sc->sc_version = "1.0";
119 sc->sc_version = "1.2";
122 sc->sc_version = "1.3";
125 sc->sc_version = "unknown";
129 sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >>
130 OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1;
131 sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >>
132 OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1;
135 * PSIM seems to report 1 too many IRQs and CPUs
144 "Version %s, supports %d CPUs and %d irqs\n",
145 sc->sc_version, sc->sc_ncpu, sc->sc_nirq);
147 for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
148 openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 15);
150 /* Reset and disable all interrupts. */
151 for (irq = 0; irq < sc->sc_nirq; irq++) {
152 x = irq; /* irq == vector. */
154 x |= OPENPIC_POLARITY_POSITIVE;
155 x |= OPENPIC_SENSE_LEVEL;
156 x |= 8 << OPENPIC_PRIORITY_SHIFT;
157 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
160 /* Reset and disable all IPIs. */
161 for (ipi = 0; ipi < 4; ipi++) {
162 x = sc->sc_nirq + ipi;
164 x |= 15 << OPENPIC_PRIORITY_SHIFT;
165 openpic_write(sc, OPENPIC_IPI_VECTOR(ipi), x);
168 /* we don't need 8259 passthrough mode */
169 x = openpic_read(sc, OPENPIC_CONFIG);
170 x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
171 openpic_write(sc, OPENPIC_CONFIG, x);
173 /* send all interrupts to cpu 0 */
174 for (irq = 0; irq < sc->sc_nirq; irq++)
175 openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0);
177 /* clear all pending interrupts */
178 for (irq = 0; irq < sc->sc_nirq; irq++) {
179 (void)openpic_read(sc, OPENPIC_PCPU_IACK(PCPU_GET(cpuid)));
180 openpic_write(sc, OPENPIC_PCPU_EOI(PCPU_GET(cpuid)), 0);
183 for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
184 openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 0);
186 powerpc_register_pic(dev, sc->sc_nirq);
196 openpic_config(device_t dev, u_int irq, enum intr_trigger trig,
197 enum intr_polarity pol)
199 struct openpic_softc *sc;
202 sc = device_get_softc(dev);
203 x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
204 if (pol == INTR_POLARITY_LOW)
205 x &= ~OPENPIC_POLARITY_POSITIVE;
207 x |= OPENPIC_POLARITY_POSITIVE;
208 if (trig == INTR_TRIGGER_EDGE)
209 x &= ~OPENPIC_SENSE_LEVEL;
211 x |= OPENPIC_SENSE_LEVEL;
212 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
216 openpic_dispatch(device_t dev, struct trapframe *tf)
218 struct openpic_softc *sc;
221 CTR1(KTR_INTR, "%s: got interrupt", __func__);
223 cpuid = PCPU_GET(cpuid);
224 sc = device_get_softc(dev);
227 vector = openpic_read(sc, OPENPIC_PCPU_IACK(cpuid));
228 vector &= OPENPIC_VECTOR_MASK;
231 powerpc_dispatch_intr(vector, tf);
236 openpic_enable(device_t dev, u_int irq, u_int vector)
238 struct openpic_softc *sc;
241 sc = device_get_softc(dev);
242 if (irq < sc->sc_nirq) {
243 x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
244 x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
246 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
248 x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
249 x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
251 openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
256 openpic_eoi(device_t dev, u_int irq __unused)
258 struct openpic_softc *sc;
260 sc = device_get_softc(dev);
261 openpic_write(sc, OPENPIC_PCPU_EOI(PCPU_GET(cpuid)), 0);
265 openpic_ipi(device_t dev, u_int cpu)
267 struct openpic_softc *sc;
269 sc = device_get_softc(dev);
270 openpic_write(sc, OPENPIC_PCPU_IPI_DISPATCH(PCPU_GET(cpuid), 0),
275 openpic_mask(device_t dev, u_int irq)
277 struct openpic_softc *sc;
280 sc = device_get_softc(dev);
281 if (irq < sc->sc_nirq) {
282 x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
284 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
286 x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
288 openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
290 openpic_write(sc, OPENPIC_PCPU_EOI(PCPU_GET(cpuid)), 0);
294 openpic_unmask(device_t dev, u_int irq)
296 struct openpic_softc *sc;
299 sc = device_get_softc(dev);
300 if (irq < sc->sc_nirq) {
301 x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
303 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
305 x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
307 openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);