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