[BACK]Return to pxa2x0_intr.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / xscale

Annotation of sys/arch/arm/xscale/pxa2x0_intr.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: pxa2x0_intr.c,v 1.15 2007/05/19 15:47:16 miod Exp $ */
                      2: /*     $NetBSD: pxa2x0_intr.c,v 1.5 2003/07/15 00:24:55 lukem Exp $    */
                      3:
                      4: /*
                      5:  * Copyright (c) 2002  Genetec Corporation.  All rights reserved.
                      6:  * Written by Hiroyuki Bessho for Genetec Corporation.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed for the NetBSD Project by
                     19:  *     Genetec Corporation.
                     20:  * 4. The name of Genetec Corporation may not be used to endorse or
                     21:  *    promote products derived from this software without specific prior
                     22:  *    written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     26:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     27:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
                     28:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     29:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     30:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     31:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     32:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     33:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     34:  * POSSIBILITY OF SUCH DAMAGE.
                     35:  */
                     36:
                     37: /*
                     38:  * IRQ handler for the Intel PXA2X0 processor.
                     39:  * It has integrated interrupt controller.
                     40:  */
                     41:
                     42: #include <sys/cdefs.h>
                     43: /*
                     44: __KERNEL_RCSID(0, "$NetBSD: pxa2x0_intr.c,v 1.5 2003/07/15 00:24:55 lukem Exp $");
                     45: */
                     46:
                     47: #include <sys/cdefs.h>
                     48:
                     49: #include <sys/param.h>
                     50: #include <sys/systm.h>
                     51: #include <sys/malloc.h>
                     52: #include <sys/evcount.h>
                     53: #include <sys/queue.h>
                     54: #include <uvm/uvm_extern.h>
                     55:
                     56: #include <machine/bus.h>
                     57: #include <machine/intr.h>
                     58: #include <machine/lock.h>
                     59:
                     60: #include <arm/xscale/pxa2x0reg.h>
                     61: #include <arm/xscale/pxa2x0var.h>
                     62: #include <arm/xscale/pxa2x0_intr.h>
                     63: #include <arm/sa11x0/sa11x0_var.h>
                     64:
                     65: /*
                     66:  * INTC autoconf glue
                     67:  */
                     68: int    pxaintc_match(struct device *, void *, void *);
                     69: void   pxaintc_attach(struct device *, struct device *, void *);
                     70:
                     71: #ifdef __NetBSD__
                     72: CFATTACH_DECL(pxaintc, sizeof(struct device),
                     73:     pxaintc_match, pxaintc_attach, NULL, NULL);
                     74: #else
                     75: struct cfattach pxaintc_ca = {
                     76:         sizeof(struct device), pxaintc_match, pxaintc_attach
                     77: };
                     78:
                     79: struct cfdriver pxaintc_cd = {
                     80:        NULL, "pxaintc", DV_DULL
                     81: };
                     82:
                     83: #endif
                     84:
                     85: static int pxaintc_attached;
                     86:
                     87: int pxa2x0_stray_interrupt(void *);
                     88: void pxa2x0_init_interrupt_masks(void);
                     89:
                     90: /*
                     91:  * interrupt dispatch table.
                     92:  */
                     93: #if 1
                     94: #define MULTIPLE_HANDLERS_ON_ONE_IRQ
                     95: #endif
                     96: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                     97: struct intrhand {
                     98:        TAILQ_ENTRY(intrhand)   ih_list;                /* link on intrq list */
                     99:        int                     (*ih_func)(void *);     /* handler */
                    100:        void                    *ih_arg;                /* arg for handler */
                    101:        char                    *ih_name;
                    102:        struct evcount          ih_count;
                    103:        int                     ih_irq;
                    104:        int                     ih_level;
                    105: };
                    106: #endif
                    107:
                    108: static struct intrhandler{
                    109: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    110:        TAILQ_HEAD(,intrhand) list;
                    111: #else
                    112:        pxa2x0_irq_handler_t func;
                    113:        char *name;
                    114:        void *arg;              /* NULL for stackframe */
                    115:        int ih_irq;
                    116:        struct evcount ih_count;
                    117: #endif
                    118: } handler[ICU_LEN];
                    119:
                    120: __volatile int softint_pending;
                    121: __volatile int current_spl_level;
                    122: /* interrupt masks for each level */
                    123: int pxa2x0_imask[NIPL];
                    124: static int extirq_level[ICU_LEN];
                    125:
                    126:
                    127: int
                    128: pxaintc_match(struct device *parent, void *cf, void *aux)
                    129: {
                    130:        struct pxaip_attach_args *pxa = aux;
                    131:
                    132:        if (pxaintc_attached || pxa->pxa_addr != PXA2X0_INTCTL_BASE)
                    133:                return (0);
                    134:
                    135:        return (1);
                    136: }
                    137:
                    138: void
                    139: pxaintc_attach(struct device *parent, struct device *self, void *args)
                    140: {
                    141:        int i;
                    142:
                    143:        pxaintc_attached = 1;
                    144:
                    145:        printf(": Interrupt Controller\n");
                    146:
                    147: #define        SAIPIC_ICCR     0x14
                    148:
                    149:        write_icu(SAIPIC_ICCR, 1);
                    150:        write_icu(SAIPIC_MR, 0);
                    151:
                    152:        for(i = 0; i < sizeof handler / sizeof handler[0]; ++i){
                    153: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    154:                TAILQ_INIT(&handler[i].list);
                    155:                extirq_level[i] = IPL_NONE;
                    156: #else
                    157:                handler[i].name = "stray";
                    158:                handler[i].func = pxa2x0_stray_interrupt;
                    159:                handler[i].arg = (void *)(u_int32_t) i;
                    160:                extirq_level[i] = IPL_SERIAL;
                    161: #endif
                    162:
                    163:        }
                    164:
                    165:        pxa2x0_init_interrupt_masks();
                    166:
                    167:        _splraise(IPL_SERIAL);
                    168:        enable_interrupts(I32_bit);
                    169: }
                    170:
                    171: /*
                    172:  * Invoked very early on from the board-specific initarm(), in order to
                    173:  * inform us the virtual address of the interrupt controller's registers.
                    174:  */
                    175: vaddr_t pxaic_base;
                    176: void
                    177: pxa2x0_intr_bootstrap(vaddr_t addr)
                    178: {
                    179:
                    180:        pxaic_base = addr;
                    181: }
                    182:
                    183: /*
                    184:  * PXA27x has MSL interface and SSP3 interrupts [0,1], USIM interface
                    185:  * and SSP2 interrupts [15,16]. PXA255 has bits [0..6,15] reserved and
                    186:  * bit [16] network SSP interrupt.  We don't need any of those, so we
                    187:  * map software interrupts to bits [0..1,15..16].  Sadly there are no
                    188:  * four contiguous bits safe enough to use on both processors.
                    189:  */
                    190: #define SI_TO_IRQBIT(si)  ((si) < 2 ? 1U<<(si) : 1U<<(15-2+(si)))
                    191:
                    192: /*
                    193:  * Map a software interrupt queue to an interrupt priority level.
                    194:  */
                    195: static const int si_to_ipl[SI_NQUEUES] = {
                    196:        IPL_SOFT,               /* SI_SOFT */
                    197:        IPL_SOFTCLOCK,          /* SI_SOFTCLOCK */
                    198:        IPL_SOFTNET,            /* SI_SOFTNET */
                    199:        IPL_SOFTSERIAL,         /* SI_SOFTSERIAL */
                    200: };
                    201:
                    202: /*
                    203:  * called from irq_entry.
                    204:  */
                    205: void
                    206: pxa2x0_irq_handler(void *arg)
                    207: {
                    208:        struct clockframe *frame = arg;
                    209:        uint32_t irqbits;
                    210:        int irqno;
                    211:        int saved_spl_level;
                    212: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    213:        struct intrhand *ih;
                    214: #endif
                    215:
                    216:        saved_spl_level = current_spl_level;
                    217:
                    218:        /* get pending IRQs */
                    219:        irqbits = read_icu(SAIPIC_IP);
                    220:
                    221:        while ((irqno = find_first_bit(irqbits)) >= 0) {
                    222:                /* XXX: Should we handle IRQs in priority order? */
                    223:
                    224:                /* raise spl to stop interrupts of lower priorities */
                    225:                if (saved_spl_level < extirq_level[irqno])
                    226:                        pxa2x0_setipl(extirq_level[irqno]);
                    227:
                    228:                /* Enable interrupt */
                    229:                enable_interrupts(I32_bit);
                    230:
                    231: #ifndef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    232:                (* handler[irqno].func)(
                    233:                        handler[irqno].arg == 0
                    234:                        ? frame : handler[irqno].arg );
                    235:                handler[irqno].ih_count.ec_count++;
                    236: #else
                    237:                TAILQ_FOREACH(ih, &handler[irqno].list, ih_list) {
                    238:                        if ((ih->ih_func)( ih->ih_arg == 0
                    239:                            ? frame : ih->ih_arg))
                    240:                                ih->ih_count.ec_count++;
                    241:                }
                    242: #endif
                    243:
                    244:                /* Disable interrupt */
                    245:                disable_interrupts(I32_bit);
                    246:
                    247:                irqbits &= ~(1<<irqno);
                    248:        }
                    249:
                    250:        /* restore spl to that was when this interrupt happen */
                    251:        pxa2x0_setipl(saved_spl_level);
                    252:
                    253:        if(softint_pending & pxa2x0_imask[current_spl_level])
                    254:                pxa2x0_do_pending();
                    255: }
                    256:
                    257: int
                    258: pxa2x0_stray_interrupt(void *cookie)
                    259: {
                    260:        int irqno = (int)cookie;
                    261:        printf("stray interrupt %d\n", irqno);
                    262:
                    263:        if (PXA2X0_IRQ_MIN <= irqno && irqno < ICU_LEN){
                    264:                int save = disable_interrupts(I32_bit);
                    265:                write_icu(SAIPIC_MR,
                    266:                    read_icu(SAIPIC_MR) & ~(1U<<irqno));
                    267:                restore_interrupts(save);
                    268:        }
                    269:
                    270:        return 0;
                    271: }
                    272:
                    273:
                    274:
                    275: /*
                    276:  * Interrupt Mask Handling
                    277:  */
                    278:
                    279: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    280: void pxa2x0_update_intr_masks(void);
                    281:
                    282: void
                    283: pxa2x0_update_intr_masks()
                    284: #else
                    285: void pxa2x0_update_intr_masks(int irqno, int level);
                    286:
                    287: void
                    288: pxa2x0_update_intr_masks(int irqno, int irqlevel)
                    289: #endif
                    290: {
                    291:        int psw;
                    292:
                    293: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    294:        int irq;
                    295: #ifdef DEBUG
                    296:        int level;
                    297: #endif
                    298:        struct intrhand *ih;
                    299:        psw = disable_interrupts(I32_bit);
                    300:
                    301:        /* First figure out which levels each IRQ uses. */
                    302:        for (irq = 0; irq < ICU_LEN; irq++) {
                    303:                int i;
                    304:                int max = IPL_NONE;
                    305:                int min = IPL_HIGH; /* XXX kill IPL_SERIAL */
                    306:                TAILQ_FOREACH(ih, &handler[irq].list, ih_list) {
                    307:                        if (ih->ih_level > max)
                    308:                                max = ih->ih_level;
                    309:
                    310:                        if (ih->ih_level < min)
                    311:                                min = ih->ih_level;
                    312:                }
                    313:
                    314:                extirq_level[irq] = max;
                    315:
                    316:                if (min == IPL_HIGH)
                    317:                        min = IPL_NONE;
                    318:
                    319:                /* Enable interrupt at lower level */
                    320:                for(i = 0; i < min; ++i)
                    321:                        pxa2x0_imask[i] |= (1 << irq);
                    322:
                    323:                /* Disable interrupt at upper level */
                    324:                for( ; i < NIPL-1; ++i)
                    325:                        pxa2x0_imask[i] &= ~(1 << irq);
                    326:        }
                    327:
                    328:        /* fixup */
                    329:        pxa2x0_imask[IPL_NONE] |=
                    330:            SI_TO_IRQBIT(SI_SOFT) |
                    331:            SI_TO_IRQBIT(SI_SOFTCLOCK) |
                    332:            SI_TO_IRQBIT(SI_SOFTNET) |
                    333:            SI_TO_IRQBIT(SI_SOFTSERIAL);
                    334:        pxa2x0_imask[IPL_SOFT] |=
                    335:            SI_TO_IRQBIT(SI_SOFTCLOCK) |
                    336:            SI_TO_IRQBIT(SI_SOFTNET) |
                    337:            SI_TO_IRQBIT(SI_SOFTSERIAL);
                    338:        pxa2x0_imask[IPL_SOFTCLOCK] |=
                    339:            SI_TO_IRQBIT(SI_SOFTNET) |
                    340:            SI_TO_IRQBIT(SI_SOFTSERIAL);
                    341:        pxa2x0_imask[IPL_SOFTNET] |=
                    342:            SI_TO_IRQBIT(SI_SOFTSERIAL);
                    343:        pxa2x0_imask[IPL_SOFTSERIAL] |=
                    344:            0;
                    345: #else
                    346:        int level; /* debug */
                    347:        int mask = 1U<<irqno;
                    348:        int i;
                    349:        psw = disable_interrupts(I32_bit);
                    350:
                    351:        for(i = 0; i < irqlevel; ++i)
                    352:                pxa2x0_imask[i] |= mask; /* Enable interrupt at lower level */
                    353:
                    354:        for( ; i < NIPL-1; ++i)
                    355:                pxa2x0_imask[i] &= ~mask; /* Disable interrupt at upper level */
                    356: #endif
                    357:
                    358:        /*
                    359:         * Enforce a hierarchy that gives "slow" device (or devices with
                    360:         * limited input buffer space/"real-time" requirements) a better
                    361:         * chance at not dropping data.
                    362:         */
                    363:        pxa2x0_imask[IPL_BIO] &= pxa2x0_imask[IPL_SOFTNET];
                    364:        pxa2x0_imask[IPL_NET] &= pxa2x0_imask[IPL_BIO];
                    365:        pxa2x0_imask[IPL_SOFTSERIAL] &= pxa2x0_imask[IPL_NET];
                    366:        pxa2x0_imask[IPL_TTY] &= pxa2x0_imask[IPL_SOFTSERIAL];
                    367:
                    368:        /*
                    369:         * splvm() blocks all interrupts that use the kernel memory
                    370:         * allocation facilities.
                    371:         */
                    372:        pxa2x0_imask[IPL_VM] &= pxa2x0_imask[IPL_TTY];
                    373:
                    374:        /*
                    375:         * Audio devices are not allowed to perform memory allocation
                    376:         * in their interrupt routines, and they have fairly "real-time"
                    377:         * requirements, so give them a high interrupt priority.
                    378:         */
                    379:        pxa2x0_imask[IPL_AUDIO] &= pxa2x0_imask[IPL_VM];
                    380:
                    381:        /*
                    382:         * splclock() must block anything that uses the scheduler.
                    383:         */
                    384:        pxa2x0_imask[IPL_CLOCK] &= pxa2x0_imask[IPL_AUDIO];
                    385:
                    386:        /*
                    387:         * splhigh() must block "everything".
                    388:         */
                    389:        pxa2x0_imask[IPL_HIGH] &= pxa2x0_imask[IPL_STATCLOCK];
                    390:
                    391:        /*
                    392:         * XXX We need serial drivers to run at the absolute highest priority
                    393:         * in order to avoid overruns, so serial > high.
                    394:         */
                    395:        pxa2x0_imask[IPL_SERIAL] &= pxa2x0_imask[IPL_HIGH];
                    396:
                    397: #ifdef DEBUG
                    398:        for (level = IPL_NONE; level < NIPL; level++) {
                    399:                printf("imask %d, %x\n", level, pxa2x0_imask[level]);
                    400:        }
                    401: #endif
                    402:
                    403: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    404:        for (irq = 0; irq < ICU_LEN; irq++) {
                    405:                int max_irq = IPL_NONE;
                    406:                TAILQ_FOREACH(ih, &handler[irq].list, ih_list) {
                    407:                        if (ih->ih_level > max_irq)
                    408:                                max_irq  = ih->ih_level;
                    409:                }
                    410:                extirq_level[irq] = max_irq;
                    411:        }
                    412: #endif
                    413:
                    414:        write_icu(SAIPIC_MR, pxa2x0_imask[current_spl_level]);
                    415:
                    416:        restore_interrupts(psw);
                    417: }
                    418:
                    419:
                    420: void
                    421: pxa2x0_init_interrupt_masks(void)
                    422: {
                    423:
                    424:        memset(pxa2x0_imask, 0, sizeof(pxa2x0_imask));
                    425:
                    426:        /*
                    427:         * IPL_NONE has soft interrupts enabled only, at least until
                    428:         * hardware handlers are installed.
                    429:         */
                    430:        pxa2x0_imask[IPL_NONE] =
                    431:            SI_TO_IRQBIT(SI_SOFT) |
                    432:            SI_TO_IRQBIT(SI_SOFTCLOCK) |
                    433:            SI_TO_IRQBIT(SI_SOFTNET) |
                    434:            SI_TO_IRQBIT(SI_SOFTSERIAL);
                    435:
                    436:        /*
                    437:         * Initialize the soft interrupt masks to block themselves.
                    438:         */
                    439:        pxa2x0_imask[IPL_SOFT] = ~SI_TO_IRQBIT(SI_SOFT);
                    440:        pxa2x0_imask[IPL_SOFTCLOCK] = ~SI_TO_IRQBIT(SI_SOFTCLOCK);
                    441:        pxa2x0_imask[IPL_SOFTNET] = ~SI_TO_IRQBIT(SI_SOFTNET);
                    442:        pxa2x0_imask[IPL_SOFTSERIAL] = ~SI_TO_IRQBIT(SI_SOFTSERIAL);
                    443:
                    444:        pxa2x0_imask[IPL_SOFT] &= pxa2x0_imask[IPL_NONE];
                    445:
                    446:        /*
                    447:         * splsoftclock() is the only interface that users of the
                    448:         * generic software interrupt facility have to block their
                    449:         * soft intrs, so splsoftclock() must also block IPL_SOFT.
                    450:         */
                    451:        pxa2x0_imask[IPL_SOFTCLOCK] &= pxa2x0_imask[IPL_SOFT];
                    452:
                    453:        /*
                    454:         * splsoftnet() must also block splsoftclock(), since we don't
                    455:         * want timer-driven network events to occur while we're
                    456:         * processing incoming packets.
                    457:         */
                    458:        pxa2x0_imask[IPL_SOFTNET] &= pxa2x0_imask[IPL_SOFTCLOCK];
                    459: }
                    460:
                    461: void
                    462: pxa2x0_do_pending(void)
                    463: {
                    464:        static __cpu_simple_lock_t processing = __SIMPLELOCK_UNLOCKED;
                    465:        int oldirqstate, spl_save;
                    466:
                    467:        if (__cpu_simple_lock_try(&processing) == 0)
                    468:                return;
                    469:
                    470:        spl_save = current_spl_level;
                    471:
                    472:        oldirqstate = disable_interrupts(I32_bit);
                    473:
                    474: #if 1
                    475: #define        DO_SOFTINT(si,ipl)                                              \
                    476:        if ((softint_pending & pxa2x0_imask[current_spl_level]) &       \
                    477:            SI_TO_IRQBIT(si)) {         \
                    478:                softint_pending &= ~SI_TO_IRQBIT(si);                   \
                    479:                if (current_spl_level < ipl)                            \
                    480:                        pxa2x0_setipl(ipl);                             \
                    481:                restore_interrupts(oldirqstate);                        \
                    482:                softintr_dispatch(si);                                  \
                    483:                oldirqstate = disable_interrupts(I32_bit);              \
                    484:                pxa2x0_setipl(spl_save);                                \
                    485:        }
                    486:
                    487:        do {
                    488:                DO_SOFTINT(SI_SOFTSERIAL,IPL_SOFTSERIAL);
                    489:                DO_SOFTINT(SI_SOFTNET, IPL_SOFTNET);
                    490:                DO_SOFTINT(SI_SOFTCLOCK, IPL_SOFTCLOCK);
                    491:                DO_SOFTINT(SI_SOFT, IPL_SOFT);
                    492:        } while( softint_pending & pxa2x0_imask[current_spl_level] );
                    493: #else
                    494:        while( (si = find_first_bit(softint_pending & pxa2x0_imask[current_spl_level])) >= 0 ){
                    495:                softint_pending &= ~SI_TO_IRQBIT(si);
                    496:                if (current_spl_level < ipl)
                    497:                        pxa2x0_setipl(ipl);
                    498:                restore_interrupts(oldirqstate);
                    499:                softintr_dispatch(si);
                    500:                oldirqstate = disable_interrupts(I32_bit);
                    501:                pxa2x0_setipl(spl_save);
                    502:        }
                    503: #endif
                    504:
                    505:        __cpu_simple_unlock(&processing);
                    506:
                    507:        restore_interrupts(oldirqstate);
                    508: }
                    509:
                    510:
                    511: #undef splx
                    512: void
                    513: splx(int ipl)
                    514: {
                    515:
                    516:        pxa2x0_splx(ipl);
                    517: }
                    518:
                    519: #undef _splraise
                    520: int
                    521: _splraise(int ipl)
                    522: {
                    523:
                    524:        return pxa2x0_splraise(ipl);
                    525: }
                    526:
                    527: #undef _spllower
                    528: int
                    529: _spllower(int ipl)
                    530: {
                    531:
                    532:        return pxa2x0_spllower(ipl);
                    533: }
                    534:
                    535: #undef _setsoftintr
                    536: void
                    537: _setsoftintr(int si)
                    538: {
                    539:
                    540:        return pxa2x0_setsoftintr(si);
                    541: }
                    542:
                    543: void *
                    544: pxa2x0_intr_establish(int irqno, int level,
                    545:     int (*func)(void *), void *arg, char *name)
                    546: {
                    547:        int psw;
                    548: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    549:        struct intrhand *ih;
                    550: #else
                    551:        struct intrhandler *ih;
                    552: #endif
                    553:
                    554:        if (irqno < PXA2X0_IRQ_MIN || irqno >= ICU_LEN)
                    555:                panic("intr_establish: bogus irq number %d", irqno);
                    556:
                    557:        psw = disable_interrupts(I32_bit);
                    558:
                    559: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    560:        /* no point in sleeping unless someone can free memory. */
                    561:        MALLOC(ih, struct intrhand *, sizeof *ih, M_DEVBUF,
                    562:            cold ? M_NOWAIT : M_WAITOK);
                    563:        if (ih == NULL)
                    564:                panic("intr_establish: can't malloc handler info");
                    565:         ih->ih_func = func;
                    566:        ih->ih_arg = arg;
                    567:        ih->ih_level = level;
                    568:        ih->ih_irq = irqno;
                    569:
                    570:        TAILQ_INSERT_TAIL(&handler[irqno].list, ih, ih_list);
                    571: #else
                    572:        ih = &handler[irqno];
                    573:        ih->arg = arg;
                    574:        ih->func = func;
                    575:        ih->name = name;
                    576:        ih->ih_irq = irqno;
                    577:        extirq_level[irqno] = level;
                    578: #endif
                    579:
                    580:        if (name != NULL)
                    581:                evcount_attach(&ih->ih_count, name, (void *)&ih->ih_irq,
                    582:                    &evcount_intr);
                    583:
                    584: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    585:        pxa2x0_update_intr_masks();
                    586: #else
                    587:        pxa2x0_update_intr_masks(irqno, level);
                    588: #endif
                    589:
                    590:        restore_interrupts(psw);
                    591:
                    592:        return (ih);
                    593: }
                    594:
                    595: void
                    596: pxa2x0_intr_disestablish(void *cookie)
                    597: {
                    598:
                    599: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    600:        int psw;
                    601:        struct intrhand *ih = cookie;
                    602:        int irqno =  ih->ih_irq;
                    603:
                    604:        psw = disable_interrupts(I32_bit);
                    605:        TAILQ_REMOVE(&handler[irqno].list, ih, ih_list);
                    606:
                    607:        FREE(ih, M_DEVBUF);
                    608:
                    609:        pxa2x0_update_intr_masks();
                    610:
                    611:        restore_interrupts(psw);
                    612: #else
                    613:        struct intrhandler *lhandler = cookie;
                    614:        int irqno;
                    615:        int psw;
                    616:        struct intrhandler *ih;
                    617:        irqno = lhandler - handler;
                    618:
                    619:        if (irqno < PXA2X0_IRQ_MIN || irqno >= ICU_LEN)
                    620:                panic("intr_disestablish: bogus irq number %d", irqno);
                    621:
                    622:        psw = disable_interrupts(I32_bit);
                    623:
                    624:        ih = &handler[irqno];
                    625:        if (ih->name != NULL)
                    626:                evcount_detach(&ih->ih_count);
                    627:
                    628:        ih->arg = (void *) irqno;
                    629:        ih->func = pxa2x0_stray_interrupt;
                    630:        ih->name = "stray";
                    631:        extirq_level[irqno] = IPL_SERIAL;
                    632:        pxa2x0_update_intr_masks(irqno, IPL_SERIAL);
                    633:
                    634:        restore_interrupts(psw);
                    635: #endif
                    636: }
                    637:
                    638: /*
                    639:  * Glue for drivers of sa11x0 compatible integrated logic.
                    640:  */
                    641: void *
                    642: sa11x0_intr_establish(sa11x0_chipset_tag_t ic, int irq, int type, int level,
                    643:     int (*ih_fun)(void *), void *ih_arg, char *name)
                    644: {
                    645:
                    646:        return pxa2x0_intr_establish(irq, level, ih_fun, ih_arg, name);
                    647: }
                    648:
                    649: void
                    650: pxa2x0_setipl(int new)
                    651: {
                    652:        u_int32_t intr_mask;
                    653:
                    654:        intr_mask = pxa2x0_imask[new];
                    655:        current_spl_level = new;
                    656:        write_icu( SAIPIC_MR, intr_mask );
                    657: }
                    658:
                    659:
                    660: void
                    661: pxa2x0_splx(int new)
                    662: {
                    663:        int psw;
                    664:
                    665:        psw = disable_interrupts(I32_bit);
                    666:        pxa2x0_setipl(new);
                    667:        restore_interrupts(psw);
                    668:
                    669:        /* If there are pending software interrupts, process them. */
                    670:        if (softint_pending & pxa2x0_imask[current_spl_level])
                    671:                pxa2x0_do_pending();
                    672: }
                    673:
                    674:
                    675: int
                    676: pxa2x0_splraise(int ipl)
                    677: {
                    678:        int     old, psw;
                    679:
                    680:        old = current_spl_level;
                    681:        if( ipl > current_spl_level ){
                    682:                psw = disable_interrupts(I32_bit);
                    683:                pxa2x0_setipl(ipl);
                    684:                restore_interrupts(psw);
                    685:        }
                    686:
                    687:        return (old);
                    688: }
                    689:
                    690: int
                    691: pxa2x0_spllower(int ipl)
                    692: {
                    693:        int old = current_spl_level;
                    694:        int psw = disable_interrupts(I32_bit);
                    695:        pxa2x0_splx(ipl);
                    696:        restore_interrupts(psw);
                    697:        return(old);
                    698: }
                    699:
                    700: void
                    701: pxa2x0_setsoftintr(int si)
                    702: {
                    703: #if 0
                    704:        atomic_set_bit( (u_int *)&softint_pending, SI_TO_IRQBIT(si) );
                    705: #else
                    706:        softint_pending |=  SI_TO_IRQBIT(si);
                    707: #endif
                    708:
                    709:        /* Process unmasked pending soft interrupts. */
                    710:        if ( softint_pending & pxa2x0_imask[current_spl_level] )
                    711:                pxa2x0_do_pending();
                    712: }
                    713:
                    714: const char *
                    715: pxa2x0_intr_string(void *cookie)
                    716: {
                    717: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
                    718:        struct intrhand *ih = cookie;
                    719: #else
                    720:        struct intrhandler *lhandler = cookie;
                    721: #endif
                    722:        static char irqstr[32];
                    723:
                    724:        if (ih == NULL)
                    725:                snprintf(irqstr, sizeof irqstr, "couldn't establish interrupt");
                    726:        else
                    727:                snprintf(irqstr, sizeof irqstr, "irq %ld", ih->ih_irq);
                    728:
                    729:        return irqstr;
                    730: }
                    731:
                    732: #ifdef DIAGNOSTIC
                    733: void
                    734: pxa2x0_splassert_check(int wantipl, const char *func)
                    735: {
                    736:        int oldipl = current_spl_level, psw;
                    737:
                    738:        if (oldipl < wantipl) {
                    739:                splassert_fail(wantipl, oldipl, func);
                    740:                /*
                    741:                 * If the splassert_ctl is set to not panic, raise the ipl
                    742:                 * in a feeble attempt to reduce damage.
                    743:                 */
                    744:                psw = disable_interrupts(I32_bit);
                    745:                pxa2x0_setipl(wantipl);
                    746:                restore_interrupts(psw);
                    747:        }
                    748: }
                    749: #endif

CVSweb