[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.3

1.3     ! nbrk        1: /*     $Id: sa1111_intr.c,v 1.2 2008/03/05 14:06:41 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));
1.3     ! nbrk       72: #if 0
1.1       nbrk       73:        /* mask all interrupts.. */
                     74:        bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTEN0, 0);
                     75:        bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTEN1, 0);
                     76:        /* ..and kill all pending ones */
                     77:        bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR0, 0xffffffff);
                     78:        bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR1, 0xffffffff);
1.3     ! nbrk       79: #endif
        !            80:        printf(": SA-1111 Interrupt Controller\n");
1.1       nbrk       81:        /* XXX IPL_AUDIO ? */
1.3     ! nbrk       82:        sc->sc_hostih = sa11x0_gpio_intr_establish(saa->sac_xintr, IST_EDGE_RISING, IPL_TTY,
1.1       nbrk       83:                                                sacic_dispatcher, NULL, "sacic");
                     84:
                     85:        sacic_sc = sc;
                     86: }
                     87:
                     88: void
                     89: sacic_intr_mask(int intrno)
                     90: {
                     91:        struct sacic_softc *sc = sacic_sc;
                     92:        bus_addr_t reg;
                     93:        uint32_t oldmask;
                     94:
                     95:        if (sc == NULL)
                     96:                panic("%s: sacic_intr_mask: sacic not configured", sc->sc_dev.dv_xname);
                     97:
                     98:        /* select apropriate register bank */
                     99:        if (intrno >= 0 && intrno < 32)
                    100:                reg = SACCIC_INTEN0;
                    101:        else {
                    102:                if (intrno >= 32 && intrno < SACCIC_LEN) {
                    103:                        reg = SACCIC_INTEN1;
                    104:                        /* adjust to be 0..31 */
                    105:                        intrno -= 32;
                    106:                }
                    107:                else
                    108:                        /* out of range */
                    109:                        panic("%s: sacic_intr_mask: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
                    110:        }
                    111:
                    112:        oldmask = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg);
                    113:        bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, oldmask & ~(1 << intrno));
                    114: }
                    115:
                    116: void
                    117: sacic_intr_unmask(int intrno)
                    118: {
                    119:        struct sacic_softc *sc = sacic_sc;
                    120:        bus_addr_t reg;
                    121:
                    122:        if (sc == NULL)
                    123:                panic("sacic_intr_mask: sacic not configured");
                    124:
                    125:        /* select apropriate register bank */
                    126:        if (intrno >= 0 && intrno < 32)
                    127:                reg = SACCIC_INTEN0;
                    128:        else {
                    129:                if (intrno >= 32 && intrno < SACCIC_LEN) {
                    130:                        reg = SACCIC_INTEN1;
                    131:                        /* adjust to be 0..31 */
                    132:                        intrno -= 32;
                    133:                }
                    134:                else
                    135:                        /* out of range */
                    136:                        panic("%s: sacic_intr_mask: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
                    137:        }
                    138:
                    139:        bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, 1 << intrno);
                    140: }
                    141:
                    142: void
                    143: sacic_intr_clear(int intrno)
                    144: {
                    145:        struct sacic_softc *sc = sacic_sc;
                    146:        bus_addr_t      reg;
                    147:
                    148:        /* select apropriate register bank */
                    149:        if (intrno >= 0 && intrno < 32)
                    150:                reg = SACCIC_INTSTATCLR0;
                    151:        else {
                    152:                if (intrno >= 32 && intrno < SACCIC_LEN) {
                    153:                        reg = SACCIC_INTSTATCLR1;
                    154:                        /* adjust to be 0..31 */
                    155:                        intrno -= 32;
                    156:                }
                    157:                else
                    158:                        /* out of range */
                    159:                        panic("%s: sacic_intr_clear: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
                    160:        }
                    161:
                    162:        bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, 1 << intrno);
                    163: }
                    164:
                    165: void
                    166: sacic_set_intr_level(int intrno, int level)
                    167: {
                    168:        /*
                    169:         * Set interrupt polarity to either falling or rising edge.
                    170:         */
                    171:        struct sacic_softc *sc = sacic_sc;
                    172:        bus_addr_t reg;
                    173:        uint32_t        oldpol;
                    174:
                    175:        if (sc == NULL)
                    176:                panic("sacic_set_intr_level: sacic not configured");
                    177:
                    178:        /* select apropriate register bank */
                    179:        if (intrno >= 0 && intrno < 32)
                    180:                reg = SACCIC_INTPOL0;
                    181:        else {
                    182:                if (intrno >= 32 && intrno < SACCIC_LEN) {
                    183:                        reg = SACCIC_INTPOL1;
                    184:                        /* adjust to be 0..31 */
                    185:                        intrno -= 32;
                    186:                }
                    187:                else
                    188:                        /* out of range */
                    189:                        panic("%s: sacic_set_intr_level: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
                    190:        }
                    191:
                    192:        oldpol = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg);
                    193:        switch (level) {
                    194:        case IST_EDGE_FALLING:
                    195:                oldpol |= 1 << intrno;
                    196:                break;
                    197:        case IST_EDGE_RISING:
                    198:                oldpol &= ~(1 << intrno);
                    199:                break;
                    200:        default:
                    201:                panic("%s: bad level: %d", sc->sc_dev.dv_xname, level);
                    202:                break;
                    203:        }
                    204:        bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, oldpol);
                    205: }
                    206:
                    207: int
                    208: sacic_dispatcher(void *arg)
                    209: {
                    210:        /*
                    211:         * Process pending interrupt(s).
                    212:         */
                    213:        struct sacic_softc *sc = sacic_sc;
                    214:        uint32_t        intstat, intbit;
                    215:        int     intrno;
                    216:
                    217:        /* check first bank */
                    218:        intstat = bus_space_read_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR0);
                    219:        for (intbit = 1, intrno = 0; intbit > 0; intbit <<= 1, intrno++) {
                    220:                if (intstat & intbit) {
                    221:                        /* interrupt set */
                    222:                        if (sc->sc_handlers[intrno] != NULL)
                    223:                                /* jump! */
                    224:                                sc->sc_handlers[intrno]->ih_func(sc->sc_handlers[intrno]->ih_arg);
                    225:
                    226:                                /* XXX acknowledge intr anyway */
                    227:                                sacic_intr_clear(intrno);
                    228:                }
                    229:        }
                    230:
                    231:        /* check second bank */
                    232:        intstat = bus_space_read_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR1);
                    233:        for (intbit = 1, intrno = 32; intbit > 0; intbit <<= 1, intrno++) {
                    234:                if (intstat & intbit) {
                    235:                        /* interrupt set */
                    236:                        if (sc->sc_handlers[intrno] != NULL)
                    237:                                /* jump! */
                    238:                                sc->sc_handlers[intrno]->ih_func(sc->sc_handlers[intrno]->ih_arg);
                    239:
                    240:                                /* XXX acknowledge intr anyway */
                    241:                                sacic_intr_clear(intrno);
                    242:                }
                    243:        }
                    244:        return(0);
                    245: }
                    246:
                    247: void
                    248: *sa11x1_intr_establish(int irq, int level, int (*func)(void *),
                    249:                void *arg, char *name)
                    250: {
                    251:        struct sacic_softc *sc = sacic_sc;
                    252:        struct sacic_intrhandler *sih;
                    253:
                    254:        if (sc == NULL)
                    255:                panic("sa11x1_intr_establish: sacic not configured");
                    256:        if (irq < 0 || irq > 31)
                    257:                panic("sa11x1_intr_establish: bogus intrno %d", irq);
                    258:
                    259:        MALLOC(sih, struct sacic_intrhandler *, sizeof(struct sacic_intrhandler),
                    260:                        M_DEVBUF, M_NOWAIT);
1.2       nbrk      261:        memset(sih, 0, sizeof(struct sacic_intrhandler));
1.1       nbrk      262:        sih->ih_xintr = irq;
                    263:        sih->ih_level = level;
                    264:        sih->ih_func = func;
                    265:        sih->ih_arg = arg;
                    266:        sih->ih_name = name;
                    267:        /* TODO evcount? */
                    268:
                    269:        sacic_set_intr_level(irq, level);
                    270:
                    271:        /* XXX silently drops previous handler */
                    272:        sc->sc_handlers[irq] = sih;
                    273:        sacic_intr_unmask(irq);
                    274:
                    275:        return(sih);
                    276: }
                    277:
                    278: void sa11x1_intr_disestablish(void *cookie)
                    279: {
1.2       nbrk      280:        /*
                    281:         * Unlink interrupt handler and free its data structures.
                    282:         */
                    283:        struct sacic_softc *sc = sacic_sc;
                    284:        struct sacic_intrhandler *sih = cookie;
                    285:
                    286:        sc->sc_handlers[sih->ih_xintr] = NULL;
                    287:
                    288:        FREE(sih, M_DEVBUF);
1.1       nbrk      289: }

CVSweb