pic_discovery.c revision 1.2 1 1.2 garbled /* $NetBSD: pic_discovery.c,v 1.2 2007/10/17 19:56:42 garbled Exp $ */
2 1.2 garbled
3 1.2 garbled /*
4 1.2 garbled * Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc.
5 1.2 garbled * All rights reserved.
6 1.2 garbled *
7 1.2 garbled * Redistribution and use in source and binary forms, with or without
8 1.2 garbled * modification, are permitted provided that the following conditions
9 1.2 garbled * are met:
10 1.2 garbled * 1. Redistributions of source code must retain the above copyright
11 1.2 garbled * notice, this list of conditions and the following disclaimer.
12 1.2 garbled * 2. Redistributions in binary form must reproduce the above copyright
13 1.2 garbled * notice, this list of conditions and the following disclaimer in the
14 1.2 garbled * documentation and/or other materials provided with the distribution.
15 1.2 garbled * 3. All advertising materials mentioning features or use of this software
16 1.2 garbled * must display the following acknowledgement:
17 1.2 garbled * This product includes software developed for the NetBSD Project by
18 1.2 garbled * Allegro Networks, Inc., and Wasabi Systems, Inc.
19 1.2 garbled * 4. The name of Allegro Networks, Inc. may not be used to endorse
20 1.2 garbled * or promote products derived from this software without specific prior
21 1.2 garbled * written permission.
22 1.2 garbled * 5. The name of Wasabi Systems, Inc. may not be used to endorse
23 1.2 garbled * or promote products derived from this software without specific prior
24 1.2 garbled * written permission.
25 1.2 garbled *
26 1.2 garbled * THIS SOFTWARE IS PROVIDED BY ALLEGRO NETWORKS, INC. AND
27 1.2 garbled * WASABI SYSTEMS, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
28 1.2 garbled * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
29 1.2 garbled * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 1.2 garbled * IN NO EVENT SHALL EITHER ALLEGRO NETWORKS, INC. OR WASABI SYSTEMS, INC.
31 1.2 garbled * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 1.2 garbled * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 1.2 garbled * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 1.2 garbled * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 1.2 garbled * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 1.2 garbled * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 1.2 garbled * POSSIBILITY OF SUCH DAMAGE.
38 1.2 garbled */
39 1.2 garbled
40 1.2 garbled /*
41 1.2 garbled * extintr.c - external interrupt management for discovery
42 1.2 garbled *
43 1.2 garbled * Interrupts are software-prioritized and preempting,
44 1.2 garbled * they are only actually masked when pending.
45 1.2 garbled * this allows avoiding slow, off-CPU mask reprogramming for spl/splx.
46 1.2 garbled * When a lower priority interrupt preempts a high one,
47 1.2 garbled * it is pended and masked. Masks are re-enabled after service.
48 1.2 garbled *
49 1.2 garbled * `ci->ci_cpl' is a "priority level" not a bitmask.
50 1.2 garbled * `irq' is a bit number in the 128 bit imask_t which reflects
51 1.2 garbled * the GT-64260 Main Cause register pair (64 bits), and
52 1.2 garbled * GPP Cause register (32 bits) interrupts.
53 1.2 garbled *
54 1.2 garbled * Intra IPL dispatch order is defined in cause_irq()
55 1.2 garbled *
56 1.2 garbled * Summary bits in cause registers are not valid IRQs
57 1.2 garbled *
58 1.2 garbled * Within a cause register bit vector ISRs are called in
59 1.2 garbled * order of IRQ (descending).
60 1.2 garbled *
61 1.2 garbled * When IRQs are shared, ISRs are called in order on the queue
62 1.2 garbled * (which is arbitrarily first-established-first-served).
63 1.2 garbled *
64 1.2 garbled * GT64260 GPP setup is for edge-triggered interrupts.
65 1.2 garbled * We maintain a mask of level-triggered type IRQs
66 1.2 garbled * and gather unlatched level from the GPP Value register.
67 1.2 garbled *
68 1.2 garbled * Software interrupts are just like regular IRQs,
69 1.2 garbled * they are established, pended, and dispatched exactly the
70 1.2 garbled * same as HW interrupts.
71 1.2 garbled *
72 1.2 garbled * 128 bit imask_t operations could be implemented with Altivec
73 1.2 garbled * ("vand", "vor", etc however no "vcntlzw" or "vffs"....)
74 1.2 garbled *
75 1.2 garbled * creation Tue Feb 6 17:27:18 PST 2001 cliff
76 1.2 garbled */
77 1.2 garbled
78 1.2 garbled #include <sys/cdefs.h>
79 1.2 garbled __KERNEL_RCSID(0, "$NetBSD: pic_discovery.c,v 1.2 2007/10/17 19:56:42 garbled Exp $");
80 1.2 garbled
81 1.2 garbled #include "opt_marvell.h"
82 1.2 garbled #include "opt_kgdb.h"
83 1.2 garbled
84 1.2 garbled #include <sys/param.h>
85 1.2 garbled #include <sys/systm.h>
86 1.2 garbled #include <sys/types.h>
87 1.2 garbled #include <sys/malloc.h>
88 1.2 garbled #include <sys/kernel.h>
89 1.2 garbled
90 1.2 garbled #include <machine/psl.h>
91 1.2 garbled #include <machine/bus.h>
92 1.2 garbled #include <machine/cpu.h>
93 1.2 garbled #include <machine/intr.h>
94 1.2 garbled #include <powerpc/pic/picvar.h>
95 1.2 garbled #ifdef KGDB
96 1.2 garbled #include <machine/db_machdep.h>
97 1.2 garbled #endif
98 1.2 garbled #include <dev/marvell/gtreg.h>
99 1.2 garbled #include <dev/marvell/gtvar.h>
100 1.2 garbled #include <dev/marvell/gtintrreg.h>
101 1.2 garbled
102 1.2 garbled #include <uvm/uvm_extern.h>
103 1.2 garbled
104 1.2 garbled #if defined(DEBUG) && defined(DDB)
105 1.2 garbled #endif
106 1.2 garbled
107 1.2 garbled #ifdef DEBUG
108 1.2 garbled # define STATIC
109 1.2 garbled int intrdebug = 0;
110 1.2 garbled # define DPRINTF(x) do { if (intrdebug) printf x ; } while (0)
111 1.2 garbled # define DPRINTFN(n, x) do { if (intrdebug > (n)) printf x ; } while (0)
112 1.2 garbled #else
113 1.2 garbled # define STATIC static
114 1.2 garbled # define DPRINTF(x)
115 1.2 garbled # define DPRINTFN(n, x)
116 1.2 garbled #endif
117 1.2 garbled
118 1.2 garbled #ifdef DIAGNOSTIC
119 1.2 garbled # define DIAGPRF(x) printf x
120 1.2 garbled #else
121 1.2 garbled # define DIAGPRF(x)
122 1.2 garbled #endif
123 1.2 garbled
124 1.2 garbled #define ILLEGAL_IRQ(x) (((x) < 0) || ((x) >= NIRQ) || \
125 1.2 garbled ((1<<((x)&IMASK_BITMASK)) & imres.bits[(x)>>IMASK_WORDSHIFT]))
126 1.2 garbled
127 1.2 garbled extern struct powerpc_bus_space gt_mem_bs_tag;
128 1.2 garbled extern bus_space_handle_t gt_memh;
129 1.2 garbled
130 1.2 garbled static const char intr_source_strings[NIRQ][16] = {
131 1.2 garbled "unknown 0", "dev", "dma", "cpu",
132 1.2 garbled "idma 01", "idma 23", "idma 45", "idma 67",
133 1.2 garbled "timer 01", "timer 23", "timer 45", "timer 67",
134 1.2 garbled "pci0-0", "pci0-1", "pci0-2", "pci0-3",
135 1.2 garbled /*16*/ "pci1-0", "ecc", "pci1-1", "pci1-2",
136 1.2 garbled "pci1-3", "pci0-outl", "pci0-outh", "pci1-outl",
137 1.2 garbled "pci1-outh", "unknown 25", "pci0-inl", "pci0-inh",
138 1.2 garbled "pci1-inl", "pci1-inh", "unknown 30", "unknown 31",
139 1.2 garbled /*32*/ "ether 0", "ether 1", "ether 2", "unknown 35",
140 1.2 garbled "sdma", "iic", "unknown 38", "brg",
141 1.2 garbled "mpsc 0", "unknown 41", "mpsc 1", "comm",
142 1.2 garbled "unknown 44", "unknown 45", "unknown 46", "unknown 47",
143 1.2 garbled /*48*/ "unknown 48", "unknown 49", "unknown 50", "unknown 51",
144 1.2 garbled "unknown 52", "unknown 53", "unknown 54", "unknown 55",
145 1.2 garbled "gppsum 0", "gppsum 1", "gppsum 2", "gppsum 3",
146 1.2 garbled "unknown 60", "unknown 61", "unknown 62", "unknown 63",
147 1.2 garbled };
148 1.2 garbled
149 1.2 garbled struct discovery_pic_ops {
150 1.2 garbled struct pic_ops dsc_pic;
151 1.2 garbled bus_space_tag_t dsc_memt;
152 1.2 garbled bus_space_tag_t dsc_memh;
153 1.2 garbled uint32_t dsc_interrupt_mask[2];
154 1.2 garbled uint8_t dsc_priority[64];
155 1.2 garbled uint8_t dsc_maxpriority[64];
156 1.2 garbled };
157 1.2 garbled
158 1.2 garbled struct gpp_pic_ops {
159 1.2 garbled struct pic_ops gpp_pic;
160 1.2 garbled bus_space_tag_t gpp_memt;
161 1.2 garbled bus_space_handle_t gpp_memh;
162 1.2 garbled uint32_t gpp_interrupt_mask;
163 1.2 garbled uint8_t gpp_priority[32];
164 1.2 garbled uint8_t gpp_maxpriority[32];
165 1.2 garbled };
166 1.2 garbled
167 1.2 garbled static void
168 1.2 garbled gpp_source_name(struct pic_ops *pic, int irq, char *name, size_t len)
169 1.2 garbled {
170 1.2 garbled snprintf(name, len, "gpp %d", irq);
171 1.2 garbled }
172 1.2 garbled
173 1.2 garbled #define GPP_RES ~GT_MPP_INTERRUPTS /* from config */
174 1.2 garbled
175 1.2 garbled static int
176 1.2 garbled gpp_get_irq(struct pic_ops *pic)
177 1.2 garbled {
178 1.2 garbled struct gpppic_ops * const gpp = (void *)pic;
179 1.2 garbled uint32_t mask;
180 1.2 garbled int maybe_irq = -1;
181 1.2 garbled int maybe_priority = IPL_NONE;
182 1.2 garbled
183 1.2 garbled #ifdef GPP_EDGE
184 1.2 garbled mask = bus_space_read_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Interrupt_Cause);
185 1.2 garbled #else
186 1.2 garbled mask = bus_space_read_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Value);
187 1.2 garbled #endif
188 1.2 garbled mask &= gpp->gpp_interrupt_mask;
189 1.2 garbled if (mask == 0)
190 1.2 garbled return NO_IRQ;
191 1.2 garbled
192 1.2 garbled while (mask != 0) {
193 1.2 garbled int irq = 32 - __builtin_clz(mask);
194 1.2 garbled if (gpp->gpp_priority[irq] > maybe_irq) {
195 1.2 garbled maybe_irq = irq;
196 1.2 garbled maybe_priority = gpp->gpp_priority[irq];
197 1.2 garbled if (maybe_priority > gpp->gpp_maxpriority[irq])
198 1.2 garbled break;
199 1.2 garbled }
200 1.2 garbled mask &= ~(1 << irq);
201 1.2 garbled }
202 1.2 garbled /*
203 1.2 garbled * We now have the highest priority IRQ.
204 1.2 garbled */
205 1.2 garbled KASSERT(maybe_irq >= 0);
206 1.2 garbled #ifdef GPP_EDGE
207 1.2 garbled mask = 1 << maybe_irq;
208 1.2 garbled bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Interrupt_Cause, mask);
209 1.2 garbled #endif
210 1.2 garbled
211 1.2 garbled return maybe_irq;
212 1.2 garbled }
213 1.2 garbled
214 1.2 garbled static void
215 1.2 garbled gpp_establish_irq(struct pic_ops *pic, int irq, int type, int pri)
216 1.2 garbled {
217 1.2 garbled struct gpppic_ops * const gpp = (void *)pic;
218 1.2 garbled const uint32_t mask = 1 << irq;
219 1.2 garbled
220 1.2 garbled KASSERT((unsigned) irq < 32);
221 1.2 garbled #ifdef GPP_EDGE
222 1.2 garbled KASSERT(type == IST_EDGE);
223 1.2 garbled #else
224 1.2 garbled KASSERT(type == IST_LEVEL);
225 1.2 garbled #endif
226 1.2 garbled
227 1.2 garbled /*
228 1.2 garbled * Set pin to input and active low.
229 1.2 garbled */
230 1.2 garbled val = bus_space_read_4(gpp->gpp_memt, gpp->gpp_memh, GT_GPP_IO_Control);
231 1.2 garbled val &= ~mask;
232 1.2 garbled bus_space_write_4(gpp->gpp_memt, gpp->gpp_memh, GT_GPP_IO_Control, val);
233 1.2 garbled
234 1.2 garbled val = bus_space_read_4(gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Level_Control);
235 1.2 garbled val |= mask;
236 1.2 garbled bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Level_Control, val);
237 1.2 garbled
238 1.2 garbled gpp->gpp_priority[irq] = pri;
239 1.2 garbled
240 1.2 garbled /*
241 1.2 garbled * recalculate the maxpriority of an interrupt. This is highest
242 1.2 garbled * priority interrupt from itself to gpp0.
243 1.2 garbled */
244 1.2 garbled pri = IPL_NONE;
245 1.2 garbled for (i = 0; i < __arraycount(gpp->gpp_priority); i++) {
246 1.2 garbled if (gpp->gpp_priority[i] > pri)
247 1.2 garbled pri = gpp->gpp_priority[i];
248 1.2 garbled gpp->gpp_maxpriority[i] = pri;
249 1.2 garbled }
250 1.2 garbled }
251 1.2 garbled
252 1.2 garbled static void
253 1.2 garbled gpp_enable_irq(struct pic_ops *pic, int irq, int type)
254 1.2 garbled {
255 1.2 garbled struct gpppic_ops * const gpp = (void *)pic;
256 1.2 garbled const uint32_t mask = 1 << irq;
257 1.2 garbled
258 1.2 garbled KASSERT(type == IST_LEVEL);
259 1.2 garbled KASSERT(gpp->gpp_priority[irq] != IPL_NONE);
260 1.2 garbled gpp->gpp_interrupt_mask |= mask;
261 1.2 garbled bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Interrupt_Mask,
262 1.2 garbled gpp->gpp_interrupt_mask);
263 1.2 garbled }
264 1.2 garbled
265 1.2 garbled static void
266 1.2 garbled gpp_disable_irq(struct pic_ops *pic, int irq)
267 1.2 garbled {
268 1.2 garbled struct gpppic_ops * const gpp = (void *)pic;
269 1.2 garbled const uint32_t mask = 1 << irq;
270 1.2 garbled
271 1.2 garbled gpp->gpp_interrupt_mask &= ~mask;
272 1.2 garbled bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Interrupt_Mask,
273 1.2 garbled gpp->gpp_interrupt_mask);
274 1.2 garbled }
275 1.2 garbled
276 1.2 garbled static void
277 1.2 garbled gpp_ack_irq(struct pic_ops *pic, int irq)
278 1.2 garbled {
279 1.2 garbled }
280 1.2 garbled
281 1.2 garbled static struct pic_ops *
282 1.2 garbled gpp_pic_setup(bus_space_tag_t memt, bus_space_handle_t memh)
283 1.2 garbled {
284 1.2 garbled struct gpppic_ops * gpp;
285 1.2 garbled uint32_t val;
286 1.2 garbled
287 1.2 garbled gpp = malloc(sizeof(*gpp), M_DEVBUF, M_NOWAIT|M_ZERO);
288 1.2 garbled if (!gpp)
289 1.2 garbled panic("gpp_pic_setup: malloc(%zu) failed", sizeof(*gpp));
290 1.2 garbled
291 1.2 garbled gpp->gpp_memt = memt;
292 1.2 garbled gpp->gpp_memh = memh;
293 1.2 garbled gpp->gpp_pic.pic_get_irq = gpp_get_irq;
294 1.2 garbled gpp->gpp_pic.pic_enable_irq = gpp_enable_irq;
295 1.2 garbled gpp->gpp_pic.pic_reenable_irq = gpp_enable_irq;
296 1.2 garbled gpp->gpp_pic.pic_disable_irq = gpp_disable_irq;
297 1.2 garbled gpp->gpp_pic.pic_ack_irq = gpp_ack_irq;
298 1.2 garbled gpp->gpp_pic.pic_establish_irq = gpp_establish_irq;
299 1.2 garbled gpp->gpp_pic.pic_source_name = gpp_source_name;
300 1.2 garbled
301 1.2 garbled /*
302 1.2 garbled * Force GPP interrupts to be level sensitive.
303 1.2 garbled */
304 1.2 garbled val = bus_space_read_4(&gpp->gpp_memt, gpp->gpp_memh, 0xf300);
305 1.2 garbled bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, 0xf300, val | 0x400);
306 1.2 garbled
307 1.2 garbled pic_add(&gpp->gpp_pic);
308 1.2 garbled
309 1.2 garbled return &gpp->gpp_pic;
310 1.2 garbled }
311 1.2 garbled
312 1.2 garbled static void
313 1.2 garbled discovery_source_name(struct pic_ops *pic, int irq, char *name, size_t len)
314 1.2 garbled {
315 1.2 garbled strlcpy(name, discovery_intr_source_strings[irq], len);
316 1.2 garbled }
317 1.2 garbled
318 1.2 garbled static int
319 1.2 garbled discovery_get_irq(struct pic_ops *pic)
320 1.2 garbled {
321 1.2 garbled struct discoverypic_ops * const dsc = (void *)pic;
322 1.2 garbled uint32_t mask;
323 1.2 garbled int irq_base = 0;
324 1.2 garbled int maybe_irq = -1;
325 1.2 garbled int maybe_priority = IPL_NONE;
326 1.2 garbled
327 1.2 garbled mask = bus_space_read_4(&dsc->dsc_memt, dsc->dsc_memh, ICR_CSC);
328 1.2 garbled if (!(mask & CSC_STAT))
329 1.2 garbled return NO_IRQ;
330 1.2 garbled irq_base = (mask & CSC_SEL) ? 32 : 0;
331 1.2 garbled mask &= dsc->dsc_interrupt_mask[(mask & CSC_SEL) ? 1 : 0];
332 1.2 garbled while (mask != 0) {
333 1.2 garbled int irq = 32 - __builtin_clz(mask);
334 1.2 garbled if (dsc->dsc_priority[irq_base + irq] > maybe_irq) {
335 1.2 garbled maybe_irq = irq_base + irq;
336 1.2 garbled maybe_priority = dsc->dsc_priority[irq_base + irq];
337 1.2 garbled if (maybe_priority > dsc->dsc_maxpriority[irq_base + irq])
338 1.2 garbled break;
339 1.2 garbled }
340 1.2 garbled mask &= ~(1 << irq);
341 1.2 garbled }
342 1.2 garbled /*
343 1.2 garbled * We now have the highest priority IRQ (except it's cascaded).
344 1.2 garbled */
345 1.2 garbled KASSERT(maybe_irq >= 0);
346 1.2 garbled return maybe_irq;
347 1.2 garbled }
348 1.2 garbled
349 1.2 garbled static void
350 1.2 garbled discovery_establish_irq(struct pic_ops *pic, int irq, int type, int pri)
351 1.2 garbled {
352 1.2 garbled struct discoverypic_ops * const dsc = (void *)pic;
353 1.2 garbled
354 1.2 garbled KASSERT((unsigned) irq < 32);
355 1.2 garbled #ifdef GPP_EDGE
356 1.2 garbled KASSERT(type == IST_EDGE);
357 1.2 garbled #else
358 1.2 garbled KASSERT(type == IST_LEVEL);
359 1.2 garbled #endif
360 1.2 garbled
361 1.2 garbled dsc->dsc_priority[irq] = pri;
362 1.2 garbled
363 1.2 garbled /*
364 1.2 garbled * recalculate the maxpriority of an interrupt. This is highest
365 1.2 garbled * priority interrupt from itself to irq 0.
366 1.2 garbled */
367 1.2 garbled pri = IPL_NONE;
368 1.2 garbled for (i = 0; i < __arraycount(dsc->dsc_priority); i++) {
369 1.2 garbled if (dsc->dsc_priority[i] > pri)
370 1.2 garbled pri = dsc->dsc_priority[i];
371 1.2 garbled dsc->dsc_maxpriority[i] = pri;
372 1.2 garbled }
373 1.2 garbled }
374 1.2 garbled
375 1.2 garbled static void
376 1.2 garbled discovery_enable_irq(struct pic_ops *pic, int irq, int type)
377 1.2 garbled {
378 1.2 garbled struct discoverypic_ops * const dsc = (void *)pic;
379 1.2 garbled const uint32_t mask = 1 << (irq & 31);
380 1.2 garbled
381 1.2 garbled KASSERT(type == IST_LEVEL);
382 1.2 garbled KASSERT(dsc->dsc_priority[irq] != IPL_NONE);
383 1.2 garbled if (irq < 32) {
384 1.2 garbled dsc->dsc_interrupt_mask[0] |= mask;
385 1.2 garbled bus_space_write_4(&dsc->dsc_memt, dsc->dsc_memh,
386 1.2 garbled ICR_MIC_LO, dsc->dsc_interrupt_mask[0]);
387 1.2 garbled } else {
388 1.2 garbled dsc->dsc_interrupt_mask[1] |= mask;
389 1.2 garbled bus_space_write_4(&dsc->dsc_memt, dsc->dsc_memh,
390 1.2 garbled ICR_MIC_HI, dsc->dsc_interrupt_mask[1]);
391 1.2 garbled }
392 1.2 garbled }
393 1.2 garbled
394 1.2 garbled static void
395 1.2 garbled discovery_disable_irq(struct pic_ops *pic, int irq)
396 1.2 garbled {
397 1.2 garbled struct discoverypic_ops * const dsc = (void *)pic;
398 1.2 garbled const uint32_t mask = 1 << (irq & 31);
399 1.2 garbled
400 1.2 garbled if (irq < 32) {
401 1.2 garbled dsc->dsc_interrupt_mask[0] &= ~mask;
402 1.2 garbled bus_space_write_4(&dsc->dsc_memt, dsc->dsc_memh,
403 1.2 garbled ICR_MIC_LO, dsc->dsc_interrupt_mask[0]);
404 1.2 garbled } else {
405 1.2 garbled dsc->dsc_interrupt_mask[1] &= ~mask;
406 1.2 garbled bus_space_write_4(&dsc->dsc_memt, dsc->dsc_memh,
407 1.2 garbled ICR_MIC_HI, dsc->dsc_interrupt_mask[1]);
408 1.2 garbled }
409 1.2 garbled }
410 1.2 garbled
411 1.2 garbled static void
412 1.2 garbled discovery_ack_irq(struct pic_ops *pic, int irq)
413 1.2 garbled {
414 1.2 garbled }
415 1.2 garbled
416 1.2 garbled void
417 1.2 garbled discoverypic_setup(bus_space_tag_t memt, bus_space_handle_t memh)
418 1.2 garbled {
419 1.2 garbled struct discoverypic_ops *dsc;
420 1.2 garbled uint32_t val;
421 1.2 garbled
422 1.2 garbled dsc = malloc(sizeof(*dsc), M_DEVBUF, M_NOWAIT|M_ZERO);
423 1.2 garbled if (!dsc)
424 1.2 garbled panic("dsc_pic_setup: malloc(%zu) failed", sizeof(*dsc));
425 1.2 garbled
426 1.2 garbled dsc->dsc_memt = memt;
427 1.2 garbled dsc->dsc_memh = memh;
428 1.2 garbled dsc->dsc_pic.pic_get_irq = dsc_get_irq;
429 1.2 garbled dsc->dsc_pic.pic_enable_irq = dsc_enable_irq;
430 1.2 garbled dsc->dsc_pic.pic_reenable_irq = dsc_enable_irq;
431 1.2 garbled dsc->dsc_pic.pic_disable_irq = dsc_disable_irq;
432 1.2 garbled dsc->dsc_pic.pic_ack_irq = dsc_ack_irq;
433 1.2 garbled dsc->dsc_pic.pic_establish_irq = dsc_establish_irq;
434 1.2 garbled dsc->dsc_pic.pic_source_name = dsc_source_name;
435 1.2 garbled
436 1.2 garbled pic_add(&dsc->dsc_pic);
437 1.2 garbled KASSERT(dsc->dsc_pic.pic_intrbase == 0);
438 1.2 garbled
439 1.2 garbled pic = dscpic_setup(memt, memh);
440 1.2 garbled intr_establish(dsc->dsc_pic.pic_intrbase + IRQ_GPP7_0,
441 1.2 garbled IST_LEVEL, IPL_NONE, pic_handle_intr, pic);
442 1.2 garbled intr_establish(dsc->dsc_pic.pic_intrbase + IRQ_GPP15_8,
443 1.2 garbled IST_LEVEL, IPL_NONE, pic_handle_intr, pic);
444 1.2 garbled intr_establish(dsc->dsc_pic.pic_intrbase + IRQ_GPP23_16,
445 1.2 garbled IST_LEVEL, IPL_NONE, pic_handle_intr, pic);
446 1.2 garbled intr_establish(dsc->dsc_pic.pic_intrbase + IRQ_GPP31_24,
447 1.2 garbled IST_LEVEL, IPL_NONE, pic_handle_intr, pic);
448 1.2 garbled }
449