Home | History | Annotate | Line # | Download | only in at91
at91aic.c revision 1.11.42.1
      1  1.11.42.1   thorpej /*	$Id: at91aic.c,v 1.11.42.1 2020/12/14 14:37:47 thorpej Exp $	*/
      2  1.11.42.1   thorpej /*	$NetBSD: at91aic.c,v 1.11.42.1 2020/12/14 14:37:47 thorpej 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.11.42.1   thorpej #include <sys/kmem.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.11  christos 		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.11.42.1   thorpej 	ih = kmem_alloc(sizeof(*ih), KM_SLEEP);
    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.11.42.1   thorpej 		kmem_free(ih, sizeof(*ih));
    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