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

1.1     ! nbrk        1: /*     $Id$    */
        !             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);
        !           267:        sih->ih_xintr = irq;
        !           268:        sih->ih_level = level;
        !           269:        sih->ih_func = func;
        !           270:        sih->ih_arg = arg;
        !           271:        sih->ih_name = name;
        !           272:        /* TODO evcount? */
        !           273:
        !           274:        sacic_set_intr_level(irq, level);
        !           275:
        !           276:        /* XXX silently drops previous handler */
        !           277:        sc->sc_handlers[irq] = sih;
        !           278:        sacic_intr_unmask(irq);
        !           279:
        !           280:        return(sih);
        !           281: }
        !           282:
        !           283: void sa11x1_intr_disestablish(void *cookie)
        !           284: {
        !           285:        /* TODO */
        !           286: }

CVSweb