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

Annotation of sys/arch/arm/s3c2xx0/s3c2800_intr.c, Revision 1.1

1.1     ! nbrk        1: /* $NetBSD: s3c2800_intr.c,v 1.9 2005/12/24 20:06:52 perry Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2002 Fujitsu Component Limited
        !             5:  * Copyright (c) 2002 Genetec Corporation
        !             6:  * All rights reserved.
        !             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. Neither the name of The Fujitsu Component Limited nor the name of
        !            17:  *    Genetec corporation may not be used to endorse or promote products
        !            18:  *    derived from this software without specific prior written permission.
        !            19:  *
        !            20:  * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
        !            21:  * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
        !            22:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
        !            23:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            24:  * DISCLAIMED.  IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
        !            25:  * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
        !            26:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
        !            27:  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
        !            28:  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
        !            29:  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
        !            30:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
        !            31:  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            32:  * SUCH DAMAGE.
        !            33:  */
        !            34:
        !            35: /*
        !            36:  * IRQ handler for Samsung S3C2800 processor.
        !            37:  * It has integrated interrupt controller.
        !            38:  */
        !            39:
        !            40: #include <sys/cdefs.h>
        !            41: __KERNEL_RCSID(0, "$NetBSD: s3c2800_intr.c,v 1.9 2005/12/24 20:06:52 perry Exp $");
        !            42:
        !            43: #include <sys/param.h>
        !            44: #include <sys/systm.h>
        !            45: #include <sys/malloc.h>
        !            46: #include <uvm/uvm_extern.h>
        !            47: #include <machine/bus.h>
        !            48: #include <machine/intr.h>
        !            49: #include <arm/cpufunc.h>
        !            50:
        !            51: #include <arm/s3c2xx0/s3c2800reg.h>
        !            52: #include <arm/s3c2xx0/s3c2800var.h>
        !            53:
        !            54: /*
        !            55:  * interrupt dispatch table.
        !            56:  */
        !            57:
        !            58: struct s3c2xx0_intr_dispatch handler[ICU_LEN];
        !            59:
        !            60: volatile int softint_pending;
        !            61:
        !            62: volatile int current_spl_level;
        !            63: volatile int intr_mask;    /* XXX: does this need to be volatile? */
        !            64: volatile int global_intr_mask = 0; /* mask some interrupts at all spl level */
        !            65:
        !            66: /* interrupt masks for each level */
        !            67: int s3c2xx0_imask[NIPL];
        !            68: int s3c2xx0_ilevel[ICU_LEN];
        !            69:
        !            70: vaddr_t intctl_base;           /* interrupt controller registers */
        !            71: #define icreg(offset) \
        !            72:        (*(volatile uint32_t *)(intctl_base+(offset)))
        !            73:
        !            74: /*
        !            75:  * Map a software interrupt queue to an interrupt priority level.
        !            76:  */
        !            77: static const int si_to_ipl[SI_NQUEUES] = {
        !            78:        IPL_SOFT,               /* SI_SOFT */
        !            79:        IPL_SOFTCLOCK,          /* SI_SOFTCLOCK */
        !            80:        IPL_SOFTNET,            /* SI_SOFTNET */
        !            81:        IPL_SOFTSERIAL,         /* SI_SOFTSERIAL */
        !            82: };
        !            83:
        !            84: /*
        !            85:  *   Clearing interrupt pending bits affects some built-in
        !            86:  * peripherals.  For example, IIC starts transmitting next data when
        !            87:  * its interrupt pending bit is cleared.
        !            88:  *   We need to leave those bits to peripheral handlers.
        !            89:  */
        !            90: #define PENDING_CLEAR_MASK     (~((1<<S3C2800_INT_IIC0)|(1<<S3C2800_INT_IIC1)))
        !            91:
        !            92: /*
        !            93:  * called from irq_entry.
        !            94:  */
        !            95: void s3c2800_irq_handler(struct clockframe *);
        !            96: void
        !            97: s3c2800_irq_handler(struct clockframe *frame)
        !            98: {
        !            99:        uint32_t irqbits;
        !           100:        int irqno;
        !           101:        int saved_spl_level;
        !           102:
        !           103:        saved_spl_level = current_spl_level;
        !           104:
        !           105:        while ((irqbits = icreg(INTCTL_IRQPND) & ICU_INT_HWMASK) != 0) {
        !           106:
        !           107:                for (irqno = ICU_LEN-1; irqno >= 0; --irqno)
        !           108:                        if (irqbits & (1<<irqno))
        !           109:                                break;
        !           110:
        !           111:                if (irqno < 0)
        !           112:                        break;
        !           113:
        !           114:                /* raise spl to stop interrupts of lower priorities */
        !           115:                if (saved_spl_level < handler[irqno].level)
        !           116:                        s3c2xx0_setipl(handler[irqno].level);
        !           117:
        !           118:                /* clear pending bit */
        !           119:                icreg(INTCTL_SRCPND) = PENDING_CLEAR_MASK & (1 << irqno);
        !           120:
        !           121:                enable_interrupts(I32_bit); /* allow nested interrupts */
        !           122:
        !           123:                (*handler[irqno].func) (
        !           124:                    handler[irqno].cookie == 0
        !           125:                    ? frame : handler[irqno].cookie);
        !           126:
        !           127:                disable_interrupts(I32_bit);
        !           128:
        !           129:                /* restore spl to that was when this interrupt happen */
        !           130:                s3c2xx0_setipl(saved_spl_level);
        !           131:        }
        !           132:
        !           133:
        !           134:        if (softint_pending & intr_mask)
        !           135:                s3c2xx0_do_pending(1);
        !           136:
        !           137: }
        !           138:
        !           139: static const u_char s3c2800_ist[] = {
        !           140:        EXTINTR_LOW,            /* NONE */
        !           141:        EXTINTR_FALLING,        /* PULSE */
        !           142:        EXTINTR_FALLING,        /* EDGE */
        !           143:        EXTINTR_LOW,            /* LEVEL */
        !           144:        EXTINTR_HIGH,
        !           145:        EXTINTR_RISING,
        !           146:        EXTINTR_BOTH,
        !           147: };
        !           148:
        !           149: void *
        !           150: s3c2800_intr_establish(int irqno, int level, int type,
        !           151:     int (* func) (void *), void *cookie)
        !           152: {
        !           153:        int save;
        !           154:
        !           155:        if (irqno < 0 || irqno >= ICU_LEN ||
        !           156:            type < IST_NONE || IST_EDGE_BOTH < type)
        !           157:                panic("intr_establish: bogus irq or type");
        !           158:
        !           159:        save = disable_interrupts(I32_bit);
        !           160:
        !           161:        handler[irqno].cookie = cookie;
        !           162:        handler[irqno].func = func;
        !           163:        handler[irqno].level = level;
        !           164:
        !           165:        s3c2xx0_update_intr_masks(irqno, level);
        !           166:
        !           167:        if (irqno <= S3C2800_INT_EXT(7)) {
        !           168:                /*
        !           169:                 * Update external interrupt control
        !           170:                 */
        !           171:                uint32_t reg;
        !           172:                u_int   trig;
        !           173:
        !           174:                trig = s3c2800_ist[type];
        !           175:
        !           176:                reg = bus_space_read_4(s3c2xx0_softc->sc_iot,
        !           177:                                       s3c2xx0_softc->sc_gpio_ioh,
        !           178:                                       GPIO_EXTINTR);
        !           179:
        !           180:                reg = reg & ~(0x0f << (4*irqno));
        !           181:                reg |= trig << (4*irqno);
        !           182:
        !           183:                bus_space_write_4(s3c2xx0_softc->sc_iot, s3c2xx0_softc->sc_gpio_ioh,
        !           184:                                  GPIO_EXTINTR, reg);
        !           185:        }
        !           186:
        !           187:        s3c2xx0_setipl(current_spl_level);
        !           188:
        !           189:        restore_interrupts(save);
        !           190:
        !           191:        return (&handler[irqno]);
        !           192: }
        !           193:
        !           194:
        !           195: static void
        !           196: init_interrupt_masks(void)
        !           197: {
        !           198:        int i;
        !           199:
        !           200:        s3c2xx0_imask[IPL_NONE] = SI_TO_IRQBIT(SI_SOFTSERIAL) |
        !           201:                SI_TO_IRQBIT(SI_SOFTNET) | SI_TO_IRQBIT(SI_SOFTCLOCK) |
        !           202:                SI_TO_IRQBIT(SI_SOFT);
        !           203:
        !           204:        s3c2xx0_imask[IPL_SOFT] = SI_TO_IRQBIT(SI_SOFTSERIAL) |
        !           205:                SI_TO_IRQBIT(SI_SOFTNET) | SI_TO_IRQBIT(SI_SOFTCLOCK);
        !           206:
        !           207:        /*
        !           208:         * splsoftclock() is the only interface that users of the
        !           209:         * generic software interrupt facility have to block their
        !           210:         * soft intrs, so splsoftclock() must also block IPL_SOFT.
        !           211:         */
        !           212:        s3c2xx0_imask[IPL_SOFTCLOCK] = SI_TO_IRQBIT(SI_SOFTSERIAL) |
        !           213:                SI_TO_IRQBIT(SI_SOFTNET);
        !           214:
        !           215:        /*
        !           216:         * splsoftnet() must also block splsoftclock(), since we don't
        !           217:         * want timer-driven network events to occur while we're
        !           218:         * processing incoming packets.
        !           219:         */
        !           220:        s3c2xx0_imask[IPL_SOFTNET] = SI_TO_IRQBIT(SI_SOFTSERIAL);
        !           221:
        !           222:        for (i = IPL_BIO; i < IPL_SOFTSERIAL; ++i)
        !           223:                s3c2xx0_imask[i] = SI_TO_IRQBIT(SI_SOFTSERIAL);
        !           224:        for (; i < NIPL; ++i)
        !           225:                s3c2xx0_imask[i] = 0;
        !           226: }
        !           227:
        !           228: void
        !           229: s3c2800_intr_init(struct s3c2800_softc *sc)
        !           230: {
        !           231:        intctl_base = (vaddr_t) bus_space_vaddr(sc->sc_sx.sc_iot,
        !           232:            sc->sc_sx.sc_intctl_ioh);
        !           233:
        !           234:        s3c2xx0_intr_mask_reg = (uint32_t *)(intctl_base + INTCTL_INTMSK);
        !           235:
        !           236:        /* clear all pending interrupt */
        !           237:        icreg(INTCTL_SRCPND) = 0xffffffff;
        !           238:
        !           239:        init_interrupt_masks();
        !           240:
        !           241:        s3c2xx0_intr_init(handler, ICU_LEN);
        !           242:
        !           243: }

CVSweb