1*6913cbefSandvar /* $Id: at91aic.c,v 1.13 2022/07/21 10:09:20 andvar Exp $ */
2*6913cbefSandvar /* $NetBSD: at91aic.c,v 1.13 2022/07/21 10:09:20 andvar Exp $ */
3c62a0ac4Smatt
4c62a0ac4Smatt /*
5c62a0ac4Smatt * Copyright (c) 2007 Embedtronics Oy.
6c62a0ac4Smatt * All rights reserved.
7c62a0ac4Smatt *
8c62a0ac4Smatt * Based on ep93xx_intr.c
9c62a0ac4Smatt * Copyright (c) 2002 The NetBSD Foundation, Inc.
10c62a0ac4Smatt * All rights reserved.
11c62a0ac4Smatt *
12c62a0ac4Smatt * This code is derived from software contributed to The NetBSD Foundation
13c62a0ac4Smatt * by Jesse Off
14c62a0ac4Smatt *
15c62a0ac4Smatt * This code is derived from software contributed to The NetBSD Foundation
16c62a0ac4Smatt * by Ichiro FUKUHARA and Naoto Shimazaki.
17c62a0ac4Smatt *
18c62a0ac4Smatt * Redistribution and use in source and binary forms, with or without
19c62a0ac4Smatt * modification, are permitted provided that the following conditions
20c62a0ac4Smatt * are met:
21c62a0ac4Smatt * 1. Redistributions of source code must retain the above copyright
22c62a0ac4Smatt * notice, this list of conditions and the following disclaimer.
23c62a0ac4Smatt * 2. Redistributions in binary form must reproduce the above copyright
24c62a0ac4Smatt * notice, this list of conditions and the following disclaimer in the
25c62a0ac4Smatt * documentation and/or other materials provided with the distribution.
26c62a0ac4Smatt *
27c62a0ac4Smatt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28c62a0ac4Smatt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29c62a0ac4Smatt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30c62a0ac4Smatt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31c62a0ac4Smatt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32c62a0ac4Smatt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33c62a0ac4Smatt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34c62a0ac4Smatt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35c62a0ac4Smatt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36c62a0ac4Smatt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37c62a0ac4Smatt * POSSIBILITY OF SUCH DAMAGE.
38c62a0ac4Smatt */
39c62a0ac4Smatt
40c62a0ac4Smatt
41c62a0ac4Smatt /*
42c62a0ac4Smatt * Interrupt support for the Atmel's AT91xx9xxx family controllers
43c62a0ac4Smatt */
44c62a0ac4Smatt
45c62a0ac4Smatt #include <sys/param.h>
46c62a0ac4Smatt #include <sys/systm.h>
4738fdb085Sthorpej #include <sys/kmem.h>
48c62a0ac4Smatt #include <sys/termios.h>
49c62a0ac4Smatt
50c62a0ac4Smatt #include <uvm/uvm_extern.h>
51c62a0ac4Smatt
52cf10107dSdyoung #include <sys/bus.h>
53c62a0ac4Smatt #include <machine/intr.h>
54c62a0ac4Smatt
55c62a0ac4Smatt #include <arm/cpufunc.h>
56c62a0ac4Smatt
57c62a0ac4Smatt #include <arm/at91/at91reg.h>
58c62a0ac4Smatt #include <arm/at91/at91var.h>
59c62a0ac4Smatt #include <arm/at91/at91aicreg.h>
60c62a0ac4Smatt #include <arm/at91/at91aicvar.h>
61c62a0ac4Smatt
62c62a0ac4Smatt #define NIRQ 32
63c62a0ac4Smatt
64c62a0ac4Smatt /* Interrupt handler queues. */
65c62a0ac4Smatt struct intrq intrq[NIRQ];
66c62a0ac4Smatt
67c62a0ac4Smatt /* Interrupts to mask at each level. */
6808a4aba7Sskrll static uint32_t aic_imask[NIPL];
69c62a0ac4Smatt
70c62a0ac4Smatt /* Software copy of the IRQs we have enabled. */
7108a4aba7Sskrll volatile uint32_t aic_intr_enabled;
72c62a0ac4Smatt
7308a4aba7Sskrll #define AICREG(reg) *((volatile uint32_t*) (AT91AIC_BASE + (reg)))
74c62a0ac4Smatt
75c62a0ac4Smatt static int at91aic_match(device_t, cfdata_t, void *);
76c62a0ac4Smatt static void at91aic_attach(device_t, device_t, void *);
77c62a0ac4Smatt
78338de10aSmatt CFATTACH_DECL_NEW(at91aic, 0,
79c62a0ac4Smatt at91aic_match, at91aic_attach, NULL, NULL);
80c62a0ac4Smatt
81c62a0ac4Smatt static int
at91aic_match(device_t parent,cfdata_t match,void * aux)82c62a0ac4Smatt at91aic_match(device_t parent, cfdata_t match, void *aux)
83c62a0ac4Smatt {
84c62a0ac4Smatt if (strcmp(match->cf_name, "at91aic") == 0)
85c62a0ac4Smatt return 2;
86c62a0ac4Smatt return 0;
87c62a0ac4Smatt }
88c62a0ac4Smatt
89c62a0ac4Smatt static void
at91aic_attach(device_t parent,device_t self,void * aux)90c62a0ac4Smatt at91aic_attach(device_t parent, device_t self, void *aux)
91c62a0ac4Smatt {
92718c4d64Saymeric int i;
93718c4d64Saymeric
94c62a0ac4Smatt (void)parent; (void)self; (void)aux;
95718c4d64Saymeric for (i = 0; i < NIRQ; i++) {
96718c4d64Saymeric evcnt_attach_dynamic(&intrq[i].iq_ev, EVCNT_TYPE_INTR,
97718c4d64Saymeric NULL, "aic", intrq[i].iq_name);
98718c4d64Saymeric }
99c62a0ac4Smatt printf("\n");
100c62a0ac4Smatt }
101c62a0ac4Smatt
102c62a0ac4Smatt static inline void
at91_set_intrmask(uint32_t aic_irqs)10308a4aba7Sskrll at91_set_intrmask(uint32_t aic_irqs)
104c62a0ac4Smatt {
105c62a0ac4Smatt AICREG(AIC_IDCR) = aic_irqs;
106c62a0ac4Smatt AICREG(AIC_IECR) = aic_intr_enabled & ~aic_irqs;
107c62a0ac4Smatt }
108c62a0ac4Smatt
109c62a0ac4Smatt static inline void
at91_enable_irq(int irq)110c62a0ac4Smatt at91_enable_irq(int irq)
111c62a0ac4Smatt {
112c62a0ac4Smatt aic_intr_enabled |= (1U << irq);
113c62a0ac4Smatt AICREG(AIC_IECR) = (1U << irq);
114c62a0ac4Smatt }
115c62a0ac4Smatt
116c62a0ac4Smatt static inline void
at91_disable_irq(int irq)117c62a0ac4Smatt at91_disable_irq(int irq)
118c62a0ac4Smatt {
119c62a0ac4Smatt aic_intr_enabled &= ~(1U << irq);
120c62a0ac4Smatt AICREG(AIC_IDCR) = (1U << irq);
121c62a0ac4Smatt }
122c62a0ac4Smatt
123c62a0ac4Smatt /*
124c62a0ac4Smatt * NOTE: This routine must be called with interrupts disabled in the CPSR.
125c62a0ac4Smatt */
126c62a0ac4Smatt static void
at91aic_calculate_masks(void)127c62a0ac4Smatt at91aic_calculate_masks(void)
128c62a0ac4Smatt {
129c62a0ac4Smatt struct intrq *iq;
130c62a0ac4Smatt struct intrhand *ih;
131c62a0ac4Smatt int irq, ipl;
132c62a0ac4Smatt
133c62a0ac4Smatt /* First, figure out which IPLs each IRQ has. */
134c62a0ac4Smatt for (irq = 0; irq < NIRQ; irq++) {
135c62a0ac4Smatt int levels = 0;
136c62a0ac4Smatt iq = &intrq[irq];
137c62a0ac4Smatt at91_disable_irq(irq);
138c62a0ac4Smatt for (ih = TAILQ_FIRST(&iq->iq_list); ih != NULL;
139c62a0ac4Smatt ih = TAILQ_NEXT(ih, ih_list))
140c62a0ac4Smatt levels |= (1U << ih->ih_ipl);
141c62a0ac4Smatt iq->iq_levels = levels;
142c62a0ac4Smatt }
143c62a0ac4Smatt
144c62a0ac4Smatt /* Next, figure out which IRQs are used by each IPL. */
145c62a0ac4Smatt for (ipl = 0; ipl < NIPL; ipl++) {
146c62a0ac4Smatt int aic_irqs = 0;
147c62a0ac4Smatt for (irq = 0; irq < AIC_NIRQ; irq++) {
148c62a0ac4Smatt if (intrq[irq].iq_levels & (1U << ipl))
149c62a0ac4Smatt aic_irqs |= (1U << irq);
150c62a0ac4Smatt }
151c62a0ac4Smatt aic_imask[ipl] = aic_irqs;
152c62a0ac4Smatt }
153c62a0ac4Smatt
154be8e5859Stsutsui /* IPL_NONE must open up all interrupts */
155be8e5859Stsutsui KASSERT(aic_imask[IPL_NONE] == 0);
156be8e5859Stsutsui KASSERT(aic_imask[IPL_SOFTCLOCK] == 0);
157be8e5859Stsutsui KASSERT(aic_imask[IPL_SOFTBIO] == 0);
158be8e5859Stsutsui KASSERT(aic_imask[IPL_SOFTNET] == 0);
159be8e5859Stsutsui KASSERT(aic_imask[IPL_SOFTSERIAL] == 0);
160c62a0ac4Smatt
161c62a0ac4Smatt /*
162be8e5859Stsutsui * Enforce a hierarchy that gives "slow" device (or devices with
163be8e5859Stsutsui * limited input buffer space/"real-time" requirements) a better
164be8e5859Stsutsui * chance at not dropping data.
165c62a0ac4Smatt */
166be8e5859Stsutsui aic_imask[IPL_SCHED] |= aic_imask[IPL_VM];
167be8e5859Stsutsui aic_imask[IPL_HIGH] |= aic_imask[IPL_SCHED];
168c62a0ac4Smatt
169c62a0ac4Smatt /*
170c62a0ac4Smatt * Now compute which IRQs must be blocked when servicing any
171c62a0ac4Smatt * given IRQ.
172c62a0ac4Smatt */
173c62a0ac4Smatt for (irq = 0; irq < MIN(NIRQ, AIC_NIRQ); irq++) {
174c62a0ac4Smatt iq = &intrq[irq];
175c62a0ac4Smatt if (TAILQ_FIRST(&iq->iq_list) != NULL)
176c62a0ac4Smatt at91_enable_irq(irq);
177c62a0ac4Smatt }
178c62a0ac4Smatt /*
179c62a0ac4Smatt * update current mask
180c62a0ac4Smatt */
181c62a0ac4Smatt at91_set_intrmask(aic_imask[curcpl()]);
182c62a0ac4Smatt }
183c62a0ac4Smatt
184c62a0ac4Smatt inline void
splx(int new)185c62a0ac4Smatt splx(int new)
186c62a0ac4Smatt {
187c62a0ac4Smatt int old;
188c62a0ac4Smatt u_int oldirqstate;
189c62a0ac4Smatt
190c62a0ac4Smatt oldirqstate = disable_interrupts(I32_bit);
191c62a0ac4Smatt old = curcpl();
192c62a0ac4Smatt if (old != new) {
193c62a0ac4Smatt set_curcpl(new);
194c62a0ac4Smatt at91_set_intrmask(aic_imask[new]);
195c62a0ac4Smatt }
196c62a0ac4Smatt restore_interrupts(oldirqstate);
197c62a0ac4Smatt #ifdef __HAVE_FAST_SOFTINTS
198c62a0ac4Smatt cpu_dosoftints();
199c62a0ac4Smatt #endif
200c62a0ac4Smatt }
201c62a0ac4Smatt
202c62a0ac4Smatt int
_splraise(int ipl)203c62a0ac4Smatt _splraise(int ipl)
204c62a0ac4Smatt {
205c62a0ac4Smatt int old;
206c62a0ac4Smatt u_int oldirqstate;
207c62a0ac4Smatt
208c62a0ac4Smatt oldirqstate = disable_interrupts(I32_bit);
209c62a0ac4Smatt old = curcpl();
210c62a0ac4Smatt if (old != ipl) {
211c62a0ac4Smatt set_curcpl(ipl);
212c62a0ac4Smatt at91_set_intrmask(aic_imask[ipl]);
213c62a0ac4Smatt }
214c62a0ac4Smatt restore_interrupts(oldirqstate);
215c62a0ac4Smatt
216c62a0ac4Smatt return (old);
217c62a0ac4Smatt }
218c62a0ac4Smatt
219c62a0ac4Smatt int
_spllower(int ipl)220c62a0ac4Smatt _spllower(int ipl)
221c62a0ac4Smatt {
222c62a0ac4Smatt int old = curcpl();
223c62a0ac4Smatt
224c62a0ac4Smatt if (old <= ipl)
225c62a0ac4Smatt return (old);
226c62a0ac4Smatt splx(ipl);
227c62a0ac4Smatt #ifdef __HAVE_FAST_SOFTINTS
228c62a0ac4Smatt cpu_dosoftints();
229c62a0ac4Smatt #endif
230c62a0ac4Smatt return (old);
231c62a0ac4Smatt }
232c62a0ac4Smatt
233c62a0ac4Smatt /*
234c62a0ac4Smatt * at91aic_init:
235c62a0ac4Smatt *
236c62a0ac4Smatt * Initialize the rest of the interrupt subsystem, making it
237c62a0ac4Smatt * ready to handle interrupts from devices.
238c62a0ac4Smatt */
239c62a0ac4Smatt void
at91aic_init(void)240c62a0ac4Smatt at91aic_init(void)
241c62a0ac4Smatt {
242c62a0ac4Smatt struct intrq *iq;
243c62a0ac4Smatt int i;
244c62a0ac4Smatt
245c62a0ac4Smatt aic_intr_enabled = 0;
246c62a0ac4Smatt
247*6913cbefSandvar // disable interrupts:
248c62a0ac4Smatt AICREG(AIC_IDCR) = -1;
249c62a0ac4Smatt
250c62a0ac4Smatt for (i = 0; i < NIRQ; i++) {
251c62a0ac4Smatt iq = &intrq[i];
252c62a0ac4Smatt TAILQ_INIT(&iq->iq_list);
253c62a0ac4Smatt
254d02e70faSchristos snprintf(iq->iq_name, sizeof(iq->iq_name), "irq %d", i);
255c62a0ac4Smatt }
256c62a0ac4Smatt
257c62a0ac4Smatt /* All interrupts should use IRQ not FIQ */
258c62a0ac4Smatt
259c62a0ac4Smatt AICREG(AIC_IDCR) = -1; /* disable interrupts */
260c62a0ac4Smatt AICREG(AIC_ICCR) = -1; /* clear all interrupts */
261c62a0ac4Smatt AICREG(AIC_DCR) = 0; /* not in debug mode, just to make sure */
262c62a0ac4Smatt for (i = 0; i < NIRQ; i++) {
263c62a0ac4Smatt AICREG(AIC_SMR(i)) = 0; /* disable interrupt */
26408a4aba7Sskrll AICREG(AIC_SVR(i)) = (uint32_t)&intrq[i]; // address of interrupt queue
265c62a0ac4Smatt }
266c62a0ac4Smatt AICREG(AIC_FVR) = 0; // fast interrupt...
267c62a0ac4Smatt AICREG(AIC_SPU) = 0; // spurious interrupt vector
268c62a0ac4Smatt
269c62a0ac4Smatt AICREG(AIC_EOICR) = 0; /* clear logic... */
270c62a0ac4Smatt AICREG(AIC_EOICR) = 0; /* clear logic... */
271c62a0ac4Smatt
272c62a0ac4Smatt at91aic_calculate_masks();
273c62a0ac4Smatt
274c62a0ac4Smatt /* Enable IRQs (don't yet use FIQs). */
275c62a0ac4Smatt enable_interrupts(I32_bit);
276c62a0ac4Smatt }
277c62a0ac4Smatt
278c62a0ac4Smatt void *
at91aic_intr_establish(int irq,int ipl,int type,int (* ih_func)(void *),void * arg)279c62a0ac4Smatt at91aic_intr_establish(int irq, int ipl, int type, int (*ih_func)(void *), void *arg)
280c62a0ac4Smatt {
281c62a0ac4Smatt struct intrq* iq;
282c62a0ac4Smatt struct intrhand* ih;
283c62a0ac4Smatt u_int oldirqstate;
284c62a0ac4Smatt unsigned ok;
285c62a0ac4Smatt uint32_t smr;
286c62a0ac4Smatt
287c62a0ac4Smatt if (irq < 0 || irq >= NIRQ)
288c62a0ac4Smatt panic("intr_establish: IRQ %d out of range", irq);
289c62a0ac4Smatt if (ipl < 0 || ipl >= NIPL)
290c62a0ac4Smatt panic("intr_establish: IPL %d out of range", ipl);
291c62a0ac4Smatt
292c62a0ac4Smatt smr = 1; // all interrupts have priority one.. ok?
293c62a0ac4Smatt switch (type) {
294c62a0ac4Smatt case _INTR_LOW_LEVEL:
295c62a0ac4Smatt smr |= AIC_SMR_SRCTYPE_LVL_LO;
296c62a0ac4Smatt break;
297c62a0ac4Smatt case INTR_HIGH_LEVEL:
298c62a0ac4Smatt smr |= AIC_SMR_SRCTYPE_LVL_HI;
299c62a0ac4Smatt break;
300c62a0ac4Smatt case INTR_FALLING_EDGE:
301c62a0ac4Smatt smr |= AIC_SMR_SRCTYPE_FALLING;
302c62a0ac4Smatt break;
303c62a0ac4Smatt case INTR_RISING_EDGE:
304c62a0ac4Smatt smr |= AIC_SMR_SRCTYPE_RISING;
305c62a0ac4Smatt break;
306c62a0ac4Smatt default:
307c62a0ac4Smatt panic("intr_establish: interrupt type %d is invalid", type);
308c62a0ac4Smatt }
309c62a0ac4Smatt
31038fdb085Sthorpej ih = kmem_alloc(sizeof(*ih), KM_SLEEP);
311c62a0ac4Smatt if (ih == NULL)
312c62a0ac4Smatt return (NULL);
313c62a0ac4Smatt
314c62a0ac4Smatt ih->ih_func = ih_func;
315c62a0ac4Smatt ih->ih_arg = arg;
316c62a0ac4Smatt ih->ih_irq = irq;
317c62a0ac4Smatt ih->ih_ipl = ipl;
318c62a0ac4Smatt
319c62a0ac4Smatt iq = &intrq[irq];
320c62a0ac4Smatt
321c62a0ac4Smatt oldirqstate = disable_interrupts(I32_bit);
322c62a0ac4Smatt if (TAILQ_FIRST(&iq->iq_list) == NULL || (iq->iq_type & ~type) == 0) {
323c62a0ac4Smatt AICREG(AIC_SMR(irq)) = smr;
324c62a0ac4Smatt iq->iq_type = type;
325c62a0ac4Smatt TAILQ_INSERT_TAIL(&iq->iq_list, ih, ih_list);
326c62a0ac4Smatt at91aic_calculate_masks();
327c62a0ac4Smatt ok = 1;
328c62a0ac4Smatt } else
329c62a0ac4Smatt ok = 0;
330c62a0ac4Smatt restore_interrupts(oldirqstate);
331c62a0ac4Smatt
332c62a0ac4Smatt if (ok) {
333c62a0ac4Smatt #ifdef AT91AIC_DEBUG
334c62a0ac4Smatt int i;
335c62a0ac4Smatt printf("\n");
336c62a0ac4Smatt for (i = 0; i < NIPL; i++) {
337c62a0ac4Smatt printf("IPL%d: aic_imask=0x%08X\n", i, aic_imask[i]);
338c62a0ac4Smatt }
339c62a0ac4Smatt #endif
340c62a0ac4Smatt } else {
34138fdb085Sthorpej kmem_free(ih, sizeof(*ih));
342c62a0ac4Smatt ih = NULL;
343c62a0ac4Smatt }
344c62a0ac4Smatt
345c62a0ac4Smatt return (ih);
346c62a0ac4Smatt }
347c62a0ac4Smatt
348c62a0ac4Smatt void
at91aic_intr_disestablish(void * cookie)349c62a0ac4Smatt at91aic_intr_disestablish(void *cookie)
350c62a0ac4Smatt {
351c62a0ac4Smatt struct intrhand* ih = cookie;
352c62a0ac4Smatt struct intrq* iq = &intrq[ih->ih_irq];
353c62a0ac4Smatt u_int oldirqstate;
354c62a0ac4Smatt
355c62a0ac4Smatt oldirqstate = disable_interrupts(I32_bit);
356c62a0ac4Smatt TAILQ_REMOVE(&iq->iq_list, ih, ih_list);
357c62a0ac4Smatt at91aic_calculate_masks();
358c62a0ac4Smatt restore_interrupts(oldirqstate);
359c62a0ac4Smatt }
360c62a0ac4Smatt
361c62a0ac4Smatt #include <arm/at91/at91reg.h>
362c62a0ac4Smatt #include <arm/at91/at91dbgureg.h>
363c62a0ac4Smatt #include <arm/at91/at91pdcreg.h>
364c62a0ac4Smatt
3651c15ddd3Sskrll static inline void intr_process(struct intrq *iq, int pcpl, struct trapframe *frame);
366c62a0ac4Smatt
367c62a0ac4Smatt static inline void
intr_process(struct intrq * iq,int pcpl,struct trapframe * frame)3681c15ddd3Sskrll intr_process(struct intrq *iq, int pcpl, struct trapframe *frame)
369c62a0ac4Smatt {
370c62a0ac4Smatt struct intrhand* ih;
371c62a0ac4Smatt u_int oldirqstate, intr;
372c62a0ac4Smatt
373c62a0ac4Smatt intr = iq - intrq;
374c62a0ac4Smatt
375c62a0ac4Smatt iq->iq_ev.ev_count++;
3766a66466fSmatt curcpu()->ci_data.cpu_nintr++;
377c62a0ac4Smatt
378c62a0ac4Smatt if ((1U << intr) & aic_imask[pcpl]) {
379c62a0ac4Smatt panic("interrupt %d should be masked! (aic_imask=0x%X)", intr, aic_imask[pcpl]);
380c62a0ac4Smatt }
381c62a0ac4Smatt
382c62a0ac4Smatt if (iq->iq_busy) {
383c62a0ac4Smatt panic("interrupt %d busy!", intr);
384c62a0ac4Smatt }
385c62a0ac4Smatt
386c62a0ac4Smatt iq->iq_busy = 1;
387c62a0ac4Smatt
388c62a0ac4Smatt for (ih = TAILQ_FIRST(&iq->iq_list); ih != NULL;
389c62a0ac4Smatt ih = TAILQ_NEXT(ih, ih_list)) {
390c62a0ac4Smatt set_curcpl(ih->ih_ipl);
391c62a0ac4Smatt at91_set_intrmask(aic_imask[ih->ih_ipl]);
392c62a0ac4Smatt oldirqstate = enable_interrupts(I32_bit);
393c62a0ac4Smatt (void) (*ih->ih_func)(ih->ih_arg ? ih->ih_arg : frame);
394c62a0ac4Smatt restore_interrupts(oldirqstate);
395c62a0ac4Smatt }
396c62a0ac4Smatt
397c62a0ac4Smatt if (!iq->iq_busy) {
398c62a0ac4Smatt panic("interrupt %d not busy!", intr);
399c62a0ac4Smatt }
400c62a0ac4Smatt iq->iq_busy = 0;
401c62a0ac4Smatt
402c62a0ac4Smatt set_curcpl(pcpl);
403c62a0ac4Smatt at91_set_intrmask(aic_imask[pcpl]);
404c62a0ac4Smatt }
405c62a0ac4Smatt
406c62a0ac4Smatt void
at91aic_intr_dispatch(struct trapframe * frame)4071c15ddd3Sskrll at91aic_intr_dispatch(struct trapframe *frame)
408c62a0ac4Smatt {
409c62a0ac4Smatt struct intrq* iq;
410c62a0ac4Smatt int pcpl = curcpl();
411c62a0ac4Smatt
412c62a0ac4Smatt iq = (struct intrq *)AICREG(AIC_IVR); // get current queue
413c62a0ac4Smatt
414c62a0ac4Smatt // OK, service interrupt
415c62a0ac4Smatt if (iq)
416c62a0ac4Smatt intr_process(iq, pcpl, frame);
417c62a0ac4Smatt
418c62a0ac4Smatt AICREG(AIC_EOICR) = 0; // end of interrupt
419c62a0ac4Smatt }
420c62a0ac4Smatt
421c62a0ac4Smatt #if 0
422c62a0ac4Smatt void
423c62a0ac4Smatt at91aic_intr_poll(int irq)
424c62a0ac4Smatt {
425c62a0ac4Smatt u_int oldirqstate;
426c62a0ac4Smatt uint32_t ipr;
427c62a0ac4Smatt int pcpl = curcpl();
428c62a0ac4Smatt
429c62a0ac4Smatt oldirqstate = disable_interrupts(I32_bit);
430c62a0ac4Smatt ipr = AICREG(AIC_IPR);
431c62a0ac4Smatt if ((ipr & (1U << irq) & ~aic_imask[pcpl]))
432c62a0ac4Smatt intr_process(&intrq[irq], pcpl, NULL);
433c62a0ac4Smatt restore_interrupts(oldirqstate);
434c62a0ac4Smatt #ifdef __HAVE_FAST_SOFTINTS
435c62a0ac4Smatt cpu_dosoftints();
436c62a0ac4Smatt #endif
437c62a0ac4Smatt }
438c62a0ac4Smatt #endif
439c62a0ac4Smatt
440c62a0ac4Smatt void
at91aic_intr_poll(void * ihp,int flags)441c62a0ac4Smatt at91aic_intr_poll(void *ihp, int flags)
442c62a0ac4Smatt {
443c62a0ac4Smatt struct intrhand* ih = ihp;
444c62a0ac4Smatt u_int oldirqstate, irq = ih->ih_irq;
445c62a0ac4Smatt uint32_t ipr;
446c62a0ac4Smatt int pcpl = curcpl();
447c62a0ac4Smatt
448c62a0ac4Smatt oldirqstate = disable_interrupts(I32_bit);
449c62a0ac4Smatt ipr = AICREG(AIC_IPR);
450c62a0ac4Smatt if ((ipr & (1U << irq))
451c62a0ac4Smatt && (flags || !(aic_imask[pcpl] & (1U << irq)))) {
452c62a0ac4Smatt set_curcpl(ih->ih_ipl);
453c62a0ac4Smatt at91_set_intrmask(aic_imask[ih->ih_ipl]);
454c62a0ac4Smatt (void)enable_interrupts(I32_bit);
455c62a0ac4Smatt (void)(*ih->ih_func)(ih->ih_arg ? ih->ih_arg : NULL);
456c62a0ac4Smatt (void)disable_interrupts(I32_bit);
457c62a0ac4Smatt set_curcpl(pcpl);
458c62a0ac4Smatt at91_set_intrmask(aic_imask[pcpl]);
459c62a0ac4Smatt }
460c62a0ac4Smatt restore_interrupts(oldirqstate);
461c62a0ac4Smatt
462c62a0ac4Smatt #ifdef __HAVE_FAST_SOFTINTS
463c62a0ac4Smatt cpu_dosoftints();
464c62a0ac4Smatt #endif
465c62a0ac4Smatt }
466