[BACK]Return to gic.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / arm / cortex

Annotation of src/sys/arch/arm/cortex/gic.c, Revision 1.7

1.7     ! matt        1: /*     $NetBSD: gic.c,v 1.6 2014/03/04 15:24:38 matt Exp $     */
1.1       matt        2: /*-
                      3:  * Copyright (c) 2012 The NetBSD Foundation, Inc.
                      4:  * All rights reserved.
                      5:  *
                      6:  * This code is derived from software contributed to The NetBSD Foundation
                      7:  * by Matt Thomas of 3am Software Foundry.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     19:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     20:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     21:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     22:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     23:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     24:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     25:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     26:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     27:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     28:  * POSSIBILITY OF SUCH DAMAGE.
                     29:  */
                     30:
1.7     ! matt       31: #include "opt_ddb.h"
        !            32:
1.1       matt       33: #define _INTR_PRIVATE
                     34:
                     35: #include <sys/cdefs.h>
1.7     ! matt       36: __KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.6 2014/03/04 15:24:38 matt Exp $");
1.1       matt       37:
                     38: #include <sys/param.h>
                     39: #include <sys/bus.h>
                     40: #include <sys/device.h>
                     41: #include <sys/evcnt.h>
                     42: #include <sys/intr.h>
1.7     ! matt       43: #include <sys/cpu.h>
1.1       matt       44: #include <sys/proc.h>
                     45: #include <sys/xcall.h>         /* for xc_ipi_handler */
                     46:
                     47: #include <arm/armreg.h>
                     48: #include <arm/cpufunc.h>
                     49: #include <arm/atomic.h>
                     50:
                     51: #include <arm/cortex/gic_reg.h>
                     52: #include <arm/cortex/mpcore_var.h>
                     53:
                     54: #define        ARMGIC_SGI_IPIBASE      (16 - NIPI)
                     55:
                     56: static int armgic_match(device_t, cfdata_t, void *);
                     57: static void armgic_attach(device_t, device_t, void *);
                     58:
                     59: static void armgic_set_priority(struct pic_softc *, int);
                     60: static void armgic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
                     61: static void armgic_block_irqs(struct pic_softc *, size_t, uint32_t);
                     62: static void armgic_establish_irq(struct pic_softc *, struct intrsource *);
                     63: #if 0
                     64: static void armgic_source_name(struct pic_softc *, int, char *, size_t);
                     65: #endif
                     66:
                     67: #ifdef MULTIPROCESSOR
                     68: static void armgic_cpu_init(struct pic_softc *, struct cpu_info *);
                     69: static void armgic_ipi_send(struct pic_softc *, const kcpuset_t *, u_long);
                     70: #endif
                     71:
                     72: static const struct pic_ops armgic_picops = {
                     73:        .pic_unblock_irqs = armgic_unblock_irqs,
                     74:        .pic_block_irqs = armgic_block_irqs,
                     75:        .pic_establish_irq = armgic_establish_irq,
                     76: #if 0
                     77:        .pic_source_name = armgic_source_name,
                     78: #endif
                     79:        .pic_set_priority = armgic_set_priority,
                     80: #ifdef MULTIPROCESSOR
                     81:        .pic_cpu_init = armgic_cpu_init,
                     82:        .pic_ipi_send = armgic_ipi_send,
                     83: #endif
                     84: };
                     85:
                     86: #define        PICTOSOFTC(pic)         ((struct armgic_softc *)(pic))
                     87:
                     88: static struct armgic_softc {
                     89:        struct pic_softc sc_pic;
                     90:        device_t sc_dev;
                     91:        bus_space_tag_t sc_memt;
1.4       matt       92:        bus_space_handle_t sc_gicch;
                     93:        bus_space_handle_t sc_gicdh;
1.1       matt       94:        size_t sc_gic_lines;
                     95:        uint32_t sc_gic_type;
                     96:        uint32_t sc_gic_valid_lines[1024/32];
                     97:        uint32_t sc_enabled_local;
1.7     ! matt       98: #ifdef MULTIPROCESSOR
        !            99:        uint32_t sc_mptargets;
        !           100: #endif
1.1       matt      101: } armgic_softc = {
                    102:        .sc_pic = {
                    103:                .pic_ops = &armgic_picops,
                    104:                .pic_name = "armgic",
                    105:        },
                    106: };
                    107:
                    108: static struct intrsource armgic_dummy_source;
                    109:
                    110: __CTASSERT(NIPL == 8);
                    111:
                    112: /*
1.6       matt      113:  * GIC register are always in little-endian.  It is assumed the bus_space
                    114:  * will do any endian conversion required.
1.1       matt      115:  */
                    116: static inline uint32_t
                    117: gicc_read(struct armgic_softc *sc, bus_size_t o)
                    118: {
1.6       matt      119:        return bus_space_read_4(sc->sc_memt, sc->sc_gicch, o);
1.1       matt      120: }
                    121:
                    122: static inline void
                    123: gicc_write(struct armgic_softc *sc, bus_size_t o, uint32_t v)
                    124: {
1.4       matt      125:        bus_space_write_4(sc->sc_memt, sc->sc_gicch, o, v);
1.1       matt      126: }
                    127:
                    128: static inline uint32_t
                    129: gicd_read(struct armgic_softc *sc, bus_size_t o)
                    130: {
1.6       matt      131:        return bus_space_read_4(sc->sc_memt, sc->sc_gicdh, o);
1.1       matt      132: }
                    133:
                    134: static inline void
                    135: gicd_write(struct armgic_softc *sc, bus_size_t o, uint32_t v)
                    136: {
1.4       matt      137:        bus_space_write_4(sc->sc_memt, sc->sc_gicdh, o, v);
1.1       matt      138: }
                    139:
                    140: /*
                    141:  * In the GIC prioritization scheme, lower numbers have higher priority.
                    142:  */
                    143: static inline uint32_t
                    144: armgic_ipl_to_priority(int ipl)
                    145: {
                    146:        return (IPL_HIGH - ipl) * GICC_PMR_PRIORITIES / NIPL;
                    147: }
                    148:
1.5       joerg     149: #if 0
1.1       matt      150: static inline int
                    151: armgic_priority_to_ipl(uint32_t priority)
                    152: {
                    153:        return IPL_HIGH - priority * NIPL / GICC_PMR_PRIORITIES;
                    154: }
1.5       joerg     155: #endif
1.1       matt      156:
                    157: static void
                    158: armgic_unblock_irqs(struct pic_softc *pic, size_t irq_base, uint32_t irq_mask)
                    159: {
                    160:        struct armgic_softc * const sc = PICTOSOFTC(pic);
                    161:        const size_t group = irq_base / 32;
                    162:
                    163:        if (group == 0)
                    164:                sc->sc_enabled_local |= irq_mask;
                    165:
                    166:        gicd_write(sc, GICD_ISENABLERn(group), irq_mask);
                    167: }
                    168:
                    169: static void
                    170: armgic_block_irqs(struct pic_softc *pic, size_t irq_base, uint32_t irq_mask)
                    171: {
                    172:        struct armgic_softc * const sc = PICTOSOFTC(pic);
                    173:        const size_t group = irq_base / 32;
                    174:
                    175:        if (group == 0)
                    176:                sc->sc_enabled_local &= ~irq_mask;
                    177:
                    178:        gicd_write(sc, GICD_ICENABLERn(group), irq_mask);
                    179: }
                    180:
                    181: static uint32_t armgic_last_priority;
                    182:
                    183: static void
                    184: armgic_set_priority(struct pic_softc *pic, int ipl)
                    185: {
                    186:        struct armgic_softc * const sc = PICTOSOFTC(pic);
                    187:
                    188:        const uint32_t priority = armgic_ipl_to_priority(ipl);
                    189:        gicc_write(sc, GICC_PMR, priority);
                    190:        armgic_last_priority = priority;
                    191: }
                    192:
                    193: #ifdef __HAVE_PIC_FAST_SOFTINTS
                    194: void
                    195: softint_init_md(lwp_t *l, u_int level, uintptr_t *machdep_p)
                    196: {
                    197:        lwp_t **lp = &l->l_cpu->ci_softlwps[level];
                    198:        KASSERT(*lp == NULL || *lp == l);
                    199:        *lp = l;
                    200:        /*
                    201:         * Really easy.  Just tell it to trigger the local CPU.
                    202:         */
                    203:        *machdep_p = GICD_SGIR_TargetListFilter_Me
                    204:            | __SHIFTIN(level, GICD_SGIR_SGIINTID);
                    205: }
                    206:
                    207: void
                    208: softint_trigger(uintptr_t machdep)
                    209: {
                    210:
                    211:        gicd_write(&armgic_softc, GICD_SGIR, machdep);
                    212: }
                    213: #endif
                    214:
                    215: void
                    216: armgic_irq_handler(void *tf)
                    217: {
                    218:        struct cpu_info * const ci = curcpu();
                    219:        struct armgic_softc * const sc = &armgic_softc;
                    220:        const int old_ipl = ci->ci_cpl;
                    221: #ifdef DIAGNOSTIC
                    222:        const int old_mtx_count = ci->ci_mtx_count;
                    223:        const int old_l_biglocks = ci->ci_curlwp->l_biglocks;
                    224: #endif
                    225: #ifdef DEBUG
                    226:        size_t n = 0;
                    227: #endif
                    228:
                    229:        ci->ci_data.cpu_nintr++;
                    230:
                    231:        KASSERTMSG(old_ipl != IPL_HIGH, "old_ipl %d pmr %#x hppir %#x",
                    232:            old_ipl, gicc_read(sc, GICC_PMR), gicc_read(sc, GICC_HPPIR));
                    233: #if 0
                    234:        printf("%s(enter): %s: pmr=%u hppir=%u\n",
                    235:            __func__, ci->ci_data.cpu_name,
                    236:            gicc_read(sc, GICC_PMR),
                    237:            gicc_read(sc, GICC_HPPIR));
                    238: #elif 0
                    239:        printf("(%u:%d", ci->ci_index, old_ipl);
                    240: #endif
                    241:
                    242:        for (;;) {
                    243:                uint32_t iar = gicc_read(sc, GICC_IAR);
                    244:                uint32_t irq = __SHIFTOUT(iar, GICC_IAR_IRQ);
                    245:                //printf(".%u", irq);
                    246:                if (irq == GICC_IAR_IRQ_SPURIOUS) {
                    247:                        iar = gicc_read(sc, GICC_IAR);
                    248:                        irq = __SHIFTOUT(iar, GICC_IAR_IRQ);
                    249:                        if (irq == GICC_IAR_IRQ_SPURIOUS)
                    250:                                break;
                    251:                        //printf(".%u", irq);
                    252:                }
                    253:
                    254:                //const uint32_t cpuid = __SHIFTOUT(iar, GICC_IAR_CPUID_MASK);
                    255:                struct intrsource * const is = sc->sc_pic.pic_sources[irq];
1.2       matt      256:                KASSERT(is != &armgic_dummy_source);
1.1       matt      257:
                    258:                /*
                    259:                 * GIC has asserted IPL for us so we can just update ci_cpl.
                    260:                 *
                    261:                 * But it's not that simple.  We may have already bumped ci_cpl
                    262:                 * due to a high priority interrupt and now we are about to
                    263:                 * dispatch one lower than the previous.  It's possible for
                    264:                 * that previous interrupt to have deferred some interrupts
                    265:                 * so we need deal with those when lowering to the current
                    266:                 * interrupt's ipl.
                    267:                 *
                    268:                 * However, if are just raising ipl, we can just update ci_cpl.
                    269:                 */
                    270: #if 0
                    271:                const int ipl = armgic_priority_to_ipl(gicc_read(sc, GICC_RPR));
                    272:                KASSERTMSG(panicstr != NULL || ipl == is->is_ipl,
                    273:                    "%s: irq %d: running ipl %d != source ipl %u",
                    274:                    ci->ci_data.cpu_name, irq, ipl, is->is_ipl);
                    275: #else
                    276:                const int ipl = is->is_ipl;
                    277: #endif
                    278:                if (__predict_false(ipl < ci->ci_cpl)) {
                    279:                        //printf("<");
                    280:                        pic_do_pending_ints(I32_bit, ipl, tf);
                    281:                        KASSERT(ci->ci_cpl == ipl);
                    282:                } else {
                    283:                        KASSERTMSG(ipl > ci->ci_cpl, "ipl %d cpl %d hw-ipl %#x",
                    284:                            ipl, ci->ci_cpl,
                    285:                            gicc_read(sc, GICC_PMR));
                    286:                        //printf(">");
                    287:                        gicc_write(sc, GICC_PMR, armgic_ipl_to_priority(ipl));
                    288:                        ci->ci_cpl = ipl;
                    289:                }
                    290:                //printf("$");
                    291:                cpsie(I32_bit);
                    292:                pic_dispatch(is, tf);
                    293:                cpsid(I32_bit);
                    294:                gicc_write(sc, GICC_EOIR, iar);
                    295: #ifdef DEBUG
                    296:                n++;
                    297:                KDASSERTMSG(n < 5, "%s: processed too many (%zu)",
                    298:                    ci->ci_data.cpu_name, n);
                    299: #endif
                    300:        }
                    301:
                    302:        // printf("%s(%p): exit (%zu dispatched)\n", __func__, tf, n);
                    303:        /*
                    304:         * Now handle any pending ints.
                    305:         */
                    306:        //printf("!");
                    307:        KASSERT(old_ipl != IPL_HIGH);
                    308:        pic_do_pending_ints(I32_bit, old_ipl, tf);
                    309:        KASSERTMSG(ci->ci_cpl == old_ipl, "ci_cpl %d old_ipl %d", ci->ci_cpl, old_ipl);
                    310:        KASSERT(old_mtx_count == ci->ci_mtx_count);
                    311:        KASSERT(old_l_biglocks == ci->ci_curlwp->l_biglocks);
                    312: #if 0
                    313:        printf("%s(exit): %s(%d): pmr=%u hppir=%u\n",
                    314:            __func__, ci->ci_data.cpu_name, ci->ci_cpl,
                    315:            gicc_read(sc, GICC_PMR),
                    316:            gicc_read(sc, GICC_HPPIR));
                    317: #elif 0
                    318:        printf("->%#x)", ((struct trapframe *)tf)->tf_pc);
                    319: #endif
                    320: }
                    321:
                    322: void
                    323: armgic_establish_irq(struct pic_softc *pic, struct intrsource *is)
                    324: {
                    325:        struct armgic_softc * const sc = PICTOSOFTC(pic);
                    326:        const size_t group = is->is_irq / 32;
                    327:        const u_int irq = is->is_irq & 31;
                    328:        const u_int byte_shift = 8 * (irq & 3);
                    329:        const u_int twopair_shift = 2 * (irq & 15);
                    330:
                    331:        KASSERTMSG(sc->sc_gic_valid_lines[group] & __BIT(irq),
                    332:            "irq %u: not valid (group[%zu]=0x%08x [0x%08x])",
                    333:            is->is_irq, group, sc->sc_gic_valid_lines[group],
                    334:            (uint32_t)__BIT(irq));
                    335:
                    336:        KASSERTMSG(is->is_type == IST_LEVEL || is->is_type == IST_EDGE,
                    337:            "irq %u: type %u unsupported", is->is_irq, is->is_type);
                    338:
                    339:        const bus_size_t targets_reg = GICD_ITARGETSRn(is->is_irq / 4);
                    340:        const bus_size_t cfg_reg = GICD_ICFGRn(is->is_irq / 16);
                    341:        uint32_t targets = gicd_read(sc, targets_reg);
                    342:        uint32_t cfg = gicd_read(sc, cfg_reg);
                    343:
                    344:        if (group > 0) {
                    345:                /*
                    346:                 * There are 4 irqs per TARGETS register.  For now bind
                    347:                 * to the primary cpu.
                    348:                 */
                    349:                targets &= ~(0xff << byte_shift);
1.7     ! matt      350: #ifdef MULTIPROCESSOR
        !           351:                if (is->is_mpsafe) {
        !           352:                        targets |= sc->sc_mptargets;
        !           353:                } else
        !           354: #endif
1.1       matt      355:                targets |= 1 << byte_shift;
                    356:                gicd_write(sc, targets_reg, targets);
                    357:
                    358:                /*
                    359:                 * There are 16 irqs per CFG register.  10=EDGE 00=LEVEL
                    360:                 */
                    361:                uint32_t new_cfg = cfg;
                    362:                uint32_t old_cfg = (cfg >> twopair_shift) & 3;
                    363:                if (is->is_type == IST_LEVEL && (old_cfg & 2) != 0) {
                    364:                        new_cfg &= ~(3 << twopair_shift);
                    365:                } else if (is->is_type == IST_EDGE && (old_cfg & 2) == 0) {
                    366:                        new_cfg |= 2 << twopair_shift;
                    367:                }
                    368:                if (new_cfg != cfg) {
                    369:                        gicd_write(sc, cfg_reg, cfg);
                    370: #if 0
                    371:                        printf("%s: irq %u: cfg changed from %#x to %#x\n",
                    372:                            pic->pic_name, is->is_irq, cfg, new_cfg);
                    373: #endif
                    374:                }
1.7     ! matt      375: #ifdef MULTIPROCESSOR
        !           376:        } else {
        !           377:                /*
        !           378:                 * All group 0 interrupts are per processor and MPSAFE by
        !           379:                 * default.
        !           380:                 */
        !           381:                is->is_mpsafe = true;
        !           382: #endif
1.1       matt      383:        }
                    384:
                    385:        /*
                    386:         * There are 4 irqs per PRIORITY register.  Map the IPL
                    387:         * to GIC priority.
                    388:         */
                    389:        const bus_size_t priority_reg = GICD_IPRIORITYRn(is->is_irq / 4);
                    390:        uint32_t priority = gicd_read(sc, priority_reg);
                    391:        priority &= ~(0xff << byte_shift);
                    392:        priority |= armgic_ipl_to_priority(is->is_ipl) << byte_shift;
                    393:        gicd_write(sc, priority_reg, priority);
                    394:
                    395: #if 0
                    396:        printf("%s: irq %u: target %#x cfg %u priority %#x (%u)\n",
                    397:            pic->pic_name, is->is_irq, (targets >> byte_shift) & 0xff,
                    398:            (cfg >> twopair_shift) & 3, (priority >> byte_shift) & 0xff,
                    399:            is->is_ipl);
                    400: #endif
                    401: }
                    402:
                    403: #ifdef MULTIPROCESSOR
                    404: static void
                    405: armgic_cpu_init_priorities(struct armgic_softc *sc)
                    406: {
                    407:        uint32_t enabled = sc->sc_enabled_local;
                    408:        for (size_t i = 0; i < 32; i += 4, enabled >>= 4) {
                    409:                /*
                    410:                 * If there are no enabled interrupts for the priority register,
                    411:                 * don't bother changing it.
                    412:                 */
                    413:                if ((enabled & 0x0f) == 0)
                    414:                        continue;
                    415:                /*
                    416:                 * Since priorities are in 3210 order, it'
                    417:                 */
                    418:                const bus_size_t priority_reg = GICD_IPRIORITYRn(i / 4);
                    419:                uint32_t priority = gicd_read(sc, priority_reg);
                    420:                uint32_t byte_mask = 0xff;
                    421:                size_t byte_shift = 0;
                    422:                for (size_t j = 0; j < 4; j++, byte_mask <<= 8, byte_shift += 8) {
                    423:                        struct intrsource * const is = sc->sc_pic.pic_sources[i+j];
                    424:                        if (is == NULL || is == &armgic_dummy_source)
                    425:                                continue;
                    426:                        priority &= ~byte_mask;
                    427:                        priority |= armgic_ipl_to_priority(is->is_ipl) << byte_shift;
                    428:                }
                    429:                gicd_write(sc, priority_reg, priority);
                    430:        }
                    431: }
                    432:
1.7     ! matt      433: static void
        !           434: armgic_cpu_init_targets(struct armgic_softc *sc)
        !           435: {
        !           436:        /*
        !           437:         * Update the mpsafe targets
        !           438:         */
        !           439:        for (size_t irq = 32; irq < sc->sc_gic_lines; irq++) {
        !           440:                struct intrsource * const is = sc->sc_pic.pic_sources[irq];
        !           441:                const bus_size_t targets_reg = GICD_ITARGETSRn(irq / 4);
        !           442:                if (is != NULL && is->is_mpsafe) {
        !           443:                        const u_int byte_shift = 0xff << (8 * (irq & 3));
        !           444:                        uint32_t targets = gicd_read(sc, targets_reg);
        !           445:                        targets |= sc->sc_mptargets << byte_shift;
        !           446:                        gicd_write(sc, targets_reg, targets);
        !           447:                }
        !           448:        }
        !           449: }
        !           450:
1.1       matt      451: void
                    452: armgic_cpu_init(struct pic_softc *pic, struct cpu_info *ci)
                    453: {
                    454:        struct armgic_softc * const sc = PICTOSOFTC(pic);
1.7     ! matt      455:        sc->sc_mptargets |= 1 << cpu_index(ci);
        !           456:        KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl);
        !           457:        if (!CPU_IS_PRIMARY(ci)) {
        !           458:                if (sc->sc_mptargets != 1) {
        !           459:                        armgic_cpu_init_targets(sc);
        !           460:                }
        !           461:                if (sc->sc_enabled_local) {
        !           462:                        armgic_cpu_init_priorities(sc);
        !           463:                        gicd_write(sc, GICD_ISENABLERn(0),
        !           464:                            sc->sc_enabled_local);
        !           465:                }
1.1       matt      466:        }
                    467:        gicc_write(sc, GICC_PMR, armgic_ipl_to_priority(ci->ci_cpl));   // set PMR
                    468:        gicc_write(sc, GICC_CTRL, GICC_CTRL_V1_Enable); // enable interrupt
                    469:        cpsie(I32_bit);                                 // allow IRQ exceptions
                    470: }
                    471:
                    472: void
                    473: armgic_ipi_send(struct pic_softc *pic, const kcpuset_t *kcp, u_long ipi)
                    474: {
                    475:        struct armgic_softc * const sc = PICTOSOFTC(pic);
                    476:
1.7     ! matt      477: #if 0
1.1       matt      478:        if (ipi == IPI_NOP) {
                    479:                __asm __volatile("sev");
                    480:                return;
                    481:        }
1.7     ! matt      482: #endif
1.1       matt      483:
1.7     ! matt      484:        uint32_t sgir = __SHIFTIN(ARMGIC_SGI_IPIBASE + ipi, GICD_SGIR_SGIINTID);
        !           485:        if (kcp != NULL) {
        !           486:                uint32_t targets;
        !           487:                kcpuset_export_u32(kcp, &targets, sizeof(targets));
        !           488:                sgir |= __SHIFTIN(targets, GICD_SGIR_TargetList);
        !           489:                sgir |= GICD_SGIR_TargetListFilter_List;
        !           490:        } else {
        !           491:                if (ncpu == 1)
        !           492:                        return;
        !           493:                sgir |= GICD_SGIR_TargetListFilter_NotMe;
        !           494:        }
1.1       matt      495:
1.7     ! matt      496:        //printf("%s: %s: %#x", __func__, curcpu()->ci_data.cpu_name, sgir);
1.1       matt      497:        gicd_write(sc, GICD_SGIR, sgir);
1.7     ! matt      498:        //printf("\n");
1.1       matt      499: }
                    500: #endif
                    501:
                    502: int
                    503: armgic_match(device_t parent, cfdata_t cf, void *aux)
                    504: {
                    505:        struct mpcore_attach_args * const mpcaa = aux;
                    506:
                    507:        if (strcmp(cf->cf_name, mpcaa->mpcaa_name) != 0)
                    508:                return 0;
1.4       matt      509:        if (!CPU_ID_CORTEX_P(cputype) || CPU_ID_CORTEX_A8_P(cputype))
1.1       matt      510:                return 0;
                    511:
                    512:        return 1;
                    513: }
                    514:
                    515: void
                    516: armgic_attach(device_t parent, device_t self, void *aux)
                    517: {
                    518:        struct armgic_softc * const sc = &armgic_softc;
                    519:        struct mpcore_attach_args * const mpcaa = aux;
                    520:
                    521:        sc->sc_dev = self;
                    522:        self->dv_private = sc;
                    523:
                    524:        sc->sc_memt = mpcaa->mpcaa_memt;        /* provided for us */
1.4       matt      525:        bus_space_subregion(sc->sc_memt, mpcaa->mpcaa_memh, mpcaa->mpcaa_off1,
                    526:            4096, &sc->sc_gicdh);
                    527:        bus_space_subregion(sc->sc_memt, mpcaa->mpcaa_memh, mpcaa->mpcaa_off2,
                    528:            4096, &sc->sc_gicch);
1.1       matt      529:
                    530:        sc->sc_gic_type = gicd_read(sc, GICD_TYPER);
                    531:        sc->sc_pic.pic_maxsources = GICD_TYPER_LINES(sc->sc_gic_type);
                    532:
                    533:        gicc_write(sc, GICC_CTRL, 0);   /* disable all interrupts */
                    534:        gicd_write(sc, GICD_CTRL, 0);   /* disable all interrupts */
                    535:
                    536:        gicc_write(sc, GICC_PMR, 0xff);
                    537:        uint32_t pmr = gicc_read(sc, GICC_PMR);
                    538:        u_int priorities = 1 << popcount32(pmr);
                    539:
                    540:        /*
                    541:         * Let's find out how many real sources we have.
                    542:         */
                    543:        for (size_t i = 0, group = 0;
                    544:             i < sc->sc_pic.pic_maxsources;
                    545:             i += 32, group++) {
                    546:                /*
                    547:                 * To figure what sources are real, one enables all interrupts
                    548:                 * and then reads back the enable mask so which ones really
                    549:                 * got enabled.
                    550:                 */
                    551:                gicd_write(sc, GICD_ISENABLERn(group), 0xffffffff);
                    552:                uint32_t valid = gicd_read(sc, GICD_ISENABLERn(group));
                    553:
                    554:                /*
                    555:                 * Now disable (clear enable) them again.
                    556:                 */
                    557:                gicd_write(sc, GICD_ICENABLERn(group), valid);
                    558:
                    559:                /*
                    560:                 * Count how many are valid.
                    561:                 */
                    562:                sc->sc_gic_lines += popcount32(valid);
                    563:                sc->sc_gic_valid_lines[group] = valid;
                    564:        }
                    565:
                    566:        pic_add(&sc->sc_pic, 0);
                    567:
                    568:        /*
                    569:         * Force the GICD to IPL_HIGH and then enable interrupts.
                    570:         */
                    571:        struct cpu_info * const ci = curcpu();
                    572:        KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl);
                    573:        armgic_set_priority(&sc->sc_pic, ci->ci_cpl);   // set PMR
                    574:        gicd_write(sc, GICD_CTRL, GICD_CTRL_Enable);    // enable Distributer
                    575:        gicc_write(sc, GICC_CTRL, GICC_CTRL_V1_Enable); // enable CPU interrupts
                    576:        cpsie(I32_bit);                                 // allow interrupt exceptions
                    577:
                    578:        /*
                    579:         * For each line that isn't valid, we set the intrsource for it to
                    580:         * point at a dummy source so that pic_intr_establish will fail for it.
                    581:         */
                    582:        for (size_t i = 0, group = 0;
                    583:             i < sc->sc_pic.pic_maxsources;
                    584:             i += 32, group++) {
                    585:                uint32_t invalid = ~sc->sc_gic_valid_lines[group];
                    586:                for (size_t j = 0; invalid && j < 32; j++, invalid >>= 1) {
                    587:                        if (invalid & 1) {
                    588:                                sc->sc_pic.pic_sources[i + j] =
                    589:                                     &armgic_dummy_source;
                    590:                        }
                    591:                }
                    592:        }
                    593: #ifdef __HAVE_PIC_FAST_SOFTINTS
                    594:        intr_establish(SOFTINT_BIO, IPL_SOFTBIO, IST_EDGE,
                    595:            pic_handle_softint, (void *)SOFTINT_BIO);
                    596:        intr_establish(SOFTINT_CLOCK, IPL_SOFTCLOCK, IST_EDGE,
                    597:            pic_handle_softint, (void *)SOFTINT_CLOCK);
                    598:        intr_establish(SOFTINT_NET, IPL_SOFTNET, IST_EDGE,
                    599:            pic_handle_softint, (void *)SOFTINT_NET);
                    600:        intr_establish(SOFTINT_SERIAL, IPL_SOFTSERIAL, IST_EDGE,
                    601:            pic_handle_softint, (void *)SOFTINT_SERIAL);
                    602: #endif
                    603: #ifdef MULTIPROCESSOR
                    604:        intr_establish(ARMGIC_SGI_IPIBASE + IPI_AST, IPL_VM, IST_EDGE,
                    605:            pic_ipi_nop, (void *)-1);
                    606:        intr_establish(ARMGIC_SGI_IPIBASE + IPI_XCALL, IPL_VM, IST_EDGE,
                    607:            pic_ipi_xcall, (void *)-1);
                    608:        intr_establish(ARMGIC_SGI_IPIBASE + IPI_NOP, IPL_VM, IST_EDGE,
                    609:            pic_ipi_nop, (void *)-1);
1.7     ! matt      610:        intr_establish(ARMGIC_SGI_IPIBASE + IPI_SHOOTDOWN, IPL_VM, IST_EDGE,
        !           611:            pic_ipi_shootdown, (void *)-1);
        !           612: #ifdef DDB
        !           613:        intr_establish(ARMGIC_SGI_IPIBASE + IPI_DDB, IPL_HIGH, IST_EDGE,
        !           614:            pic_ipi_ddb, NULL);
1.1       matt      615: #endif
                    616: #ifdef __HAVE_PREEMPTION
                    617:        intr_establish(ARMGIC_SGI_IPIBASE + IPI_KPREEMPT, IPL_VM, IST_EDGE,
                    618:            pic_ipi_nop, (void *)-1);
                    619: #endif
                    620:        armgic_cpu_init(&sc->sc_pic, curcpu());
                    621: #endif
                    622:
                    623:        aprint_normal(": Generic Interrupt Controller, "
                    624:            "%zu sources (%zu valid)\n",
                    625:            sc->sc_pic.pic_maxsources, sc->sc_gic_lines);
                    626:
                    627:        const u_int ppis = popcount32(sc->sc_gic_valid_lines[0] >> 16);
                    628:        const u_int sgis = popcount32(sc->sc_gic_valid_lines[0] & 0xffff);
                    629:        aprint_normal_dev(sc->sc_dev, "%u Priorities, %zu SPIs, %u PPIs, %u SGIs\n",
                    630:            priorities, sc->sc_gic_lines - ppis - sgis, ppis, sgis);
                    631: }
                    632:
                    633: CFATTACH_DECL_NEW(armgic, 0,
                    634:     armgic_match, armgic_attach, NULL, NULL);

CVSweb <webmaster@jp.NetBSD.org>