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