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