1 /*-
2 * Copyright (C) 2002 Benno Rice.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
13 *
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.
24 *
25 * $FreeBSD: releng/8.0/sys/powerpc/powerpc/openpic.c 193909 2009-06-10 12:47:54Z grehan $
26 */
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/bus.h>
31 #include <sys/conf.h>
32 #include <sys/kernel.h>
33 #include <sys/rman.h>
34
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>
41
42 #include <vm/vm.h>
43 #include <vm/pmap.h>
44
45 #include <machine/openpicreg.h>
46 #include <machine/openpicvar.h>
47
48 #include "pic_if.h"
49
50 devclass_t openpic_devclass;
51
52 /*
53 * Local routines
54 */
55
56 static __inline uint32_t
57 openpic_read(struct openpic_softc *sc, u_int reg)
58 {
59 return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg));
60 }
61
62 static __inline void
63 openpic_write(struct openpic_softc *sc, u_int reg, uint32_t val)
64 {
65 bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val);
66 }
67
68 static __inline void
69 openpic_set_priority(struct openpic_softc *sc, int pri)
70 {
71 u_int tpr;
72 uint32_t x;
73
74 tpr = OPENPIC_PCPU_TPR(PCPU_GET(cpuid));
75 x = openpic_read(sc, tpr);
76 x &= ~OPENPIC_TPR_MASK;
77 x |= pri;
78 openpic_write(sc, tpr, x);
79 }
80
81 int
82 openpic_attach(device_t dev)
83 {
84 struct openpic_softc *sc;
85 u_int cpu, ipi, irq;
86 u_int32_t x;
87
88 sc = device_get_softc(dev);
89 sc->sc_dev = dev;
90
91 sc->sc_rid = 0;
92 sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
93 RF_ACTIVE);
94
95 if (sc->sc_memr == NULL) {
96 device_printf(dev, "Could not alloc mem resource!\n");
97 return (ENXIO);
98 }
99
100 sc->sc_bt = rman_get_bustag(sc->sc_memr);
101 sc->sc_bh = rman_get_bushandle(sc->sc_memr);
102
103 x = openpic_read(sc, OPENPIC_FEATURE);
104 switch (x & OPENPIC_FEATURE_VERSION_MASK) {
105 case 1:
106 sc->sc_version = "1.0";
107 break;
108 case 2:
109 sc->sc_version = "1.2";
110 break;
111 case 3:
112 sc->sc_version = "1.3";
113 break;
114 default:
115 sc->sc_version = "unknown";
116 break;
117 }
118
119 sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >>
120 OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1;
121 sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >>
122 OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1;
123
124 /*
125 * PSIM seems to report 1 too many IRQs and CPUs
126 */
127 if (sc->sc_psim) {
128 sc->sc_nirq--;
129 sc->sc_ncpu--;
130 }
131
132 if (bootverbose)
133 device_printf(dev,
134 "Version %s, supports %d CPUs and %d irqs\n",
135 sc->sc_version, sc->sc_ncpu, sc->sc_nirq);
136
137 for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
138 openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 15);
139
140 /* Reset and disable all interrupts. */
141 for (irq = 0; irq < sc->sc_nirq; irq++) {
142 x = irq; /* irq == vector. */
143 x |= OPENPIC_IMASK;
144 x |= OPENPIC_POLARITY_POSITIVE;
145 x |= OPENPIC_SENSE_LEVEL;
146 x |= 8 << OPENPIC_PRIORITY_SHIFT;
147 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
148 }
149
150 /* Reset and disable all IPIs. */
151 for (ipi = 0; ipi < 4; ipi++) {
152 x = sc->sc_nirq + ipi;
153 x |= OPENPIC_IMASK;
154 x |= 15 << OPENPIC_PRIORITY_SHIFT;
155 openpic_write(sc, OPENPIC_IPI_VECTOR(ipi), x);
156 }
157
158 /* we don't need 8259 passthrough mode */
159 x = openpic_read(sc, OPENPIC_CONFIG);
160 x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
161 openpic_write(sc, OPENPIC_CONFIG, x);
162
163 /* send all interrupts to cpu 0 */
164 for (irq = 0; irq < sc->sc_nirq; irq++)
165 openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0);
166
167 /* clear all pending interrupts */
168 for (irq = 0; irq < sc->sc_nirq; irq++) {
169 (void)openpic_read(sc, OPENPIC_PCPU_IACK(PCPU_GET(cpuid)));
170 openpic_write(sc, OPENPIC_PCPU_EOI(PCPU_GET(cpuid)), 0);
171 }
172
173 for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
174 openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 0);
175
176 powerpc_register_pic(dev, sc->sc_nirq);
177
178 return (0);
179 }
180
181 /*
182 * PIC I/F methods
183 */
184
185 void
186 openpic_config(device_t dev, u_int irq, enum intr_trigger trig,
187 enum intr_polarity pol)
188 {
189 struct openpic_softc *sc;
190 uint32_t x;
191
192 sc = device_get_softc(dev);
193 x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
194 if (pol == INTR_POLARITY_LOW)
195 x &= ~OPENPIC_POLARITY_POSITIVE;
196 else
197 x |= OPENPIC_POLARITY_POSITIVE;
198 if (trig == INTR_TRIGGER_EDGE)
199 x &= ~OPENPIC_SENSE_LEVEL;
200 else
201 x |= OPENPIC_SENSE_LEVEL;
202 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
203 }
204
205 void
206 openpic_dispatch(device_t dev, struct trapframe *tf)
207 {
208 struct openpic_softc *sc;
209 u_int cpuid, vector;
210
211 CTR1(KTR_INTR, "%s: got interrupt", __func__);
212
213 cpuid = PCPU_GET(cpuid);
214 sc = device_get_softc(dev);
215
216 while (1) {
217 vector = openpic_read(sc, OPENPIC_PCPU_IACK(cpuid));
218 vector &= OPENPIC_VECTOR_MASK;
219 if (vector == 255)
220 break;
221 powerpc_dispatch_intr(vector, tf);
222 }
223 }
224
225 void
226 openpic_enable(device_t dev, u_int irq, u_int vector)
227 {
228 struct openpic_softc *sc;
229 uint32_t x;
230
231 sc = device_get_softc(dev);
232 if (irq < sc->sc_nirq) {
233 x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
234 x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
235 x |= vector;
236 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
237 } else {
238 x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
239 x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
240 x |= vector;
241 openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
242 }
243 }
244
245 void
246 openpic_eoi(device_t dev, u_int irq __unused)
247 {
248 struct openpic_softc *sc;
249
250 sc = device_get_softc(dev);
251 openpic_write(sc, OPENPIC_PCPU_EOI(PCPU_GET(cpuid)), 0);
252 }
253
254 void
255 openpic_ipi(device_t dev, u_int cpu)
256 {
257 struct openpic_softc *sc;
258
259 sc = device_get_softc(dev);
260 openpic_write(sc, OPENPIC_PCPU_IPI_DISPATCH(PCPU_GET(cpuid), 0),
261 1u << cpu);
262 }
263
264 void
265 openpic_mask(device_t dev, u_int irq)
266 {
267 struct openpic_softc *sc;
268 uint32_t x;
269
270 sc = device_get_softc(dev);
271 if (irq < sc->sc_nirq) {
272 x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
273 x |= OPENPIC_IMASK;
274 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
275 } else {
276 x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
277 x |= OPENPIC_IMASK;
278 openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
279 }
280 openpic_write(sc, OPENPIC_PCPU_EOI(PCPU_GET(cpuid)), 0);
281 }
282
283 void
284 openpic_unmask(device_t dev, u_int irq)
285 {
286 struct openpic_softc *sc;
287 uint32_t x;
288
289 sc = device_get_softc(dev);
290 if (irq < sc->sc_nirq) {
291 x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
292 x &= ~OPENPIC_IMASK;
293 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
294 } else {
295 x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
296 x &= ~OPENPIC_IMASK;
297 openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
298 }
299 }
Cache object: f98574d4212108c043a14349b64a1ea3
|