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

Annotation of sys/arch/arm/sa11x0/sa1111_intr.c, Revision 1.2

1.2     ! nbrk        1: /*     $Id: sa1111_intr.c,v 1.1 2008/03/05 11:19:00 nbrk Exp $ */
1.1       nbrk        2: #include <sys/cdefs.h>
                      3:
                      4: #include <sys/param.h>
                      5: #include <sys/systm.h>
                      6: #include <sys/device.h>
                      7: #include <sys/malloc.h>
                      8: #include <sys/evcount.h>
                      9: #include <sys/queue.h>
                     10: #include <uvm/uvm_extern.h>
                     11:
                     12: #include <machine/bus.h>
                     13: #include <machine/intr.h>
                     14: #include <machine/lock.h>
                     15:
                     16: #include <arm/sa11x0/sa11x0_intr.h>
                     17: #include <arm/sa11x0/sa11x0_gpiovar.h>
                     18: #include <arm/sa11x0/sa11x1_var.h>
                     19: #include <arm/sa11x0/sa1111_reg.h>
                     20: #include <arm/sa11x0/sa1111_intr.h>
                     21: /*
                     22:  * TODO:
                     23:  * - SPL
                     24:  */
                     25:
                     26: /*
                     27:  * Autoconf glue.
                     28:  */
                     29: int    sacic_match(struct device *, void *, void *);
                     30: void   sacic_attach(struct device *, struct device *, void *);
                     31: int    sacic_dispatcher(void *arg);
                     32: void   sacic_intr_mask(int intrno);
                     33: void   sacic_intr_unmask(int intrno);
                     34: void   sacic_intr_clear(int intrno);
                     35: void   sacic_set_intr_level(int intrno, int level);
                     36:
                     37: struct cfattach sacic_ca = {
                     38:         sizeof(struct sacic_softc), sacic_match, sacic_attach
                     39: };
                     40:
                     41: struct cfdriver sacic_cd = {
                     42:        NULL, "sacic", DV_DULL
                     43: };
                     44:
                     45: struct sacic_softc *sacic_sc;
                     46:
                     47: int
                     48: sacic_match(struct device *parent, void *cf, void *aux)
                     49: {
                     50:        struct sacc_attach_args *saa = aux;
                     51:
                     52:        if (sacic_sc != NULL || saa->sac_typecookie != SACC_TYPE_INTC)
                     53:                return(0);
                     54:
                     55:        return(1);
                     56: }
                     57:
                     58: void
                     59: sacic_attach(struct device *parent, struct device *self, void *aux)
                     60: {
                     61:        /*
                     62:         * Initialize ourselfes and establish our dispatcher on host irq xintr.
                     63:         */
                     64:        struct sacic_softc *sc = (struct sacic_softc *)self;
                     65:        struct sacc_attach_args *saa = aux;
                     66:
                     67:        sc->sc_bust = saa->sac_iot;
                     68:        sc->sc_bush = saa->sac_bush;
                     69:
                     70:        /* NULLify handlers */
                     71:        memset(sc->sc_handlers, 0, sizeof(sc->sc_handlers));
                     72:        /* mask all interrupts.. */
                     73:        bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTEN0, 0);
                     74:        bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTEN1, 0);
                     75:        /* ..and kill all pending ones */
                     76:        bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR0, 0xffffffff);
                     77:        bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR1, 0xffffffff);
                     78:
                     79:        /* XXX IPL_AUDIO ? */
                     80:        sc->sc_hostih = sa11x0_gpio_intr_establish(saa->sac_xintr, IST_EDGE_RISING, IPL_AUDIO,
                     81:                                                sacic_dispatcher, NULL, "sacic");
                     82:
                     83:        sacic_sc = sc;
                     84: }
                     85:
                     86: void
                     87: sacic_intr_mask(int intrno)
                     88: {
                     89:        struct sacic_softc *sc = sacic_sc;
                     90:        bus_addr_t reg;
                     91:        uint32_t oldmask;
                     92:
                     93:        if (sc == NULL)
                     94:                panic("%s: sacic_intr_mask: sacic not configured", sc->sc_dev.dv_xname);
                     95:
                     96:        /* select apropriate register bank */
                     97:        if (intrno >= 0 && intrno < 32)
                     98:                reg = SACCIC_INTEN0;
                     99:        else {
                    100:                if (intrno >= 32 && intrno < SACCIC_LEN) {
                    101:                        reg = SACCIC_INTEN1;
                    102:                        /* adjust to be 0..31 */
                    103:                        intrno -= 32;
                    104:                }
                    105:                else
                    106:                        /* out of range */
                    107:                        panic("%s: sacic_intr_mask: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
                    108:        }
                    109:
                    110:        oldmask = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg);
                    111:        bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, oldmask & ~(1 << intrno));
                    112: }
                    113:
                    114: void
                    115: sacic_intr_unmask(int intrno)
                    116: {
                    117:        struct sacic_softc *sc = sacic_sc;
                    118:        bus_addr_t reg;
                    119:
                    120:        if (sc == NULL)
                    121:                panic("sacic_intr_mask: sacic not configured");
                    122:
                    123:        /* select apropriate register bank */
                    124:        if (intrno >= 0 && intrno < 32)
                    125:                reg = SACCIC_INTEN0;
                    126:        else {
                    127:                if (intrno >= 32 && intrno < SACCIC_LEN) {
                    128:                        reg = SACCIC_INTEN1;
                    129:                        /* adjust to be 0..31 */
                    130:                        intrno -= 32;
                    131:                }
                    132:                else
                    133:                        /* out of range */
                    134:                        panic("%s: sacic_intr_mask: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
                    135:        }
                    136:
                    137:        bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, 1 << intrno);
                    138: }
                    139:
                    140: void
                    141: sacic_intr_clear(int intrno)
                    142: {
                    143:        struct sacic_softc *sc = sacic_sc;
                    144:        bus_addr_t      reg;
                    145:
                    146:        /* select apropriate register bank */
                    147:        if (intrno >= 0 && intrno < 32)
                    148:                reg = SACCIC_INTSTATCLR0;
                    149:        else {
                    150:                if (intrno >= 32 && intrno < SACCIC_LEN) {
                    151:                        reg = SACCIC_INTSTATCLR1;
                    152:                        /* adjust to be 0..31 */
                    153:                        intrno -= 32;
                    154:                }
                    155:                else
                    156:                        /* out of range */
                    157:                        panic("%s: sacic_intr_clear: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
                    158:        }
                    159:
                    160:        bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, 1 << intrno);
                    161: }
                    162:
                    163: void
                    164: sacic_set_intr_level(int intrno, int level)
                    165: {
                    166:        /*
                    167:         * Set interrupt polarity to either falling or rising edge.
                    168:         */
                    169:        struct sacic_softc *sc = sacic_sc;
                    170:        bus_addr_t reg;
                    171:        uint32_t        oldpol;
                    172:
                    173:        if (sc == NULL)
                    174:                panic("sacic_set_intr_level: sacic not configured");
                    175:
                    176:        /* select apropriate register bank */
                    177:        if (intrno >= 0 && intrno < 32)
                    178:                reg = SACCIC_INTPOL0;
                    179:        else {
                    180:                if (intrno >= 32 && intrno < SACCIC_LEN) {
                    181:                        reg = SACCIC_INTPOL1;
                    182:                        /* adjust to be 0..31 */
                    183:                        intrno -= 32;
                    184:                }
                    185:                else
                    186:                        /* out of range */
                    187:                        panic("%s: sacic_set_intr_level: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
                    188:        }
                    189:
                    190:        oldpol = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg);
                    191:        switch (level) {
                    192:        case IST_EDGE_FALLING:
                    193:                oldpol |= 1 << intrno;
                    194:                break;
                    195:        case IST_EDGE_RISING:
                    196:                oldpol &= ~(1 << intrno);
                    197:                break;
                    198:        default:
                    199:                panic("%s: bad level: %d", sc->sc_dev.dv_xname, level);
                    200:                break;
                    201:        }
                    202:        bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, oldpol);
                    203: }
                    204:
                    205: int
                    206: sacic_dispatcher(void *arg)
                    207: {
                    208:        /*
                    209:         * Process pending interrupt(s).
                    210:         */
                    211:        struct sacic_softc *sc = sacic_sc;
                    212:        uint32_t        intstat, intbit;
                    213:        int     intrno;
                    214:
                    215:        /* check first bank */
                    216:        intstat = bus_space_read_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR0);
                    217:        for (intbit = 1, intrno = 0; intbit > 0; intbit <<= 1, intrno++) {
                    218:                if (intstat & intbit) {
                    219:                        /* interrupt set */
                    220:                        if (sc->sc_handlers[intrno] != NULL)
                    221:                                /* jump! */
                    222:                                sc->sc_handlers[intrno]->ih_func(sc->sc_handlers[intrno]->ih_arg);
                    223:                        else
                    224:                                /* no handler */
                    225:                                printf("%s: sacic_dispatcher: warning, no handler for pending intrno %d\n",
                    226:                                                sc->sc_dev.dv_xname, intrno);
                    227:
                    228:                                /* XXX acknowledge intr anyway */
                    229:                                sacic_intr_clear(intrno);
                    230:                }
                    231:        }
                    232:
                    233:        /* check second bank */
                    234:        intstat = bus_space_read_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR1);
                    235:        for (intbit = 1, intrno = 32; intbit > 0; intbit <<= 1, intrno++) {
                    236:                if (intstat & intbit) {
                    237:                        /* interrupt set */
                    238:                        if (sc->sc_handlers[intrno] != NULL)
                    239:                                /* jump! */
                    240:                                sc->sc_handlers[intrno]->ih_func(sc->sc_handlers[intrno]->ih_arg);
                    241:                        else
                    242:                                /* no handler */
                    243:                                printf("%s: sacic_dispatcher: warning, no handler for pending intrno %d\n",
                    244:                                                sc->sc_dev.dv_xname, intrno);
                    245:
                    246:                                /* XXX acknowledge intr anyway */
                    247:                                sacic_intr_clear(intrno);
                    248:                }
                    249:        }
                    250:        return(0);
                    251: }
                    252:
                    253: void
                    254: *sa11x1_intr_establish(int irq, int level, int (*func)(void *),
                    255:                void *arg, char *name)
                    256: {
                    257:        struct sacic_softc *sc = sacic_sc;
                    258:        struct sacic_intrhandler *sih;
                    259:
                    260:        if (sc == NULL)
                    261:                panic("sa11x1_intr_establish: sacic not configured");
                    262:        if (irq < 0 || irq > 31)
                    263:                panic("sa11x1_intr_establish: bogus intrno %d", irq);
                    264:
                    265:        MALLOC(sih, struct sacic_intrhandler *, sizeof(struct sacic_intrhandler),
                    266:                        M_DEVBUF, M_NOWAIT);
1.2     ! nbrk      267:        memset(sih, 0, sizeof(struct sacic_intrhandler));
1.1       nbrk      268:        sih->ih_xintr = irq;
                    269:        sih->ih_level = level;
                    270:        sih->ih_func = func;
                    271:        sih->ih_arg = arg;
                    272:        sih->ih_name = name;
                    273:        /* TODO evcount? */
                    274:
                    275:        sacic_set_intr_level(irq, level);
                    276:
                    277:        /* XXX silently drops previous handler */
                    278:        sc->sc_handlers[irq] = sih;
                    279:        sacic_intr_unmask(irq);
                    280:
                    281:        return(sih);
                    282: }
                    283:
                    284: void sa11x1_intr_disestablish(void *cookie)
                    285: {
1.2     ! nbrk      286:        /*
        !           287:         * Unlink interrupt handler and free its data structures.
        !           288:         */
        !           289:        struct sacic_softc *sc = sacic_sc;
        !           290:        struct sacic_intrhandler *sih = cookie;
        !           291:
        !           292:        sc->sc_handlers[sih->ih_xintr] = NULL;
        !           293:
        !           294:        FREE(sih, M_DEVBUF);
1.1       nbrk      295: }

CVSweb