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