Module Name: src Committed By: jmcneill Date: Sun Jun 18 22:11:50 UTC 2017
Modified Files: src/sys/arch/arm/cortex: gic.c Log Message: Don't assume that CPU index = GIC CPU interface number. We can determine the current CPU interface number by reading from the read-only GICD_ITARGETSR0 through GICD_ITARGETSR7 registers. This gets interrupts working on Exynos 5422, where the boot processor has GIC CPU interface #4. To generate a diff of this commit: cvs rdiff -u -r1.23 -r1.24 src/sys/arch/arm/cortex/gic.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/cortex/gic.c diff -u src/sys/arch/arm/cortex/gic.c:1.23 src/sys/arch/arm/cortex/gic.c:1.24 --- src/sys/arch/arm/cortex/gic.c:1.23 Mon Jun 5 20:02:11 2017 +++ src/sys/arch/arm/cortex/gic.c Sun Jun 18 22:11:50 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: gic.c,v 1.23 2017/06/05 20:02:11 skrll Exp $ */ +/* $NetBSD: gic.c,v 1.24 2017/06/18 22:11:50 jmcneill Exp $ */ /*- * Copyright (c) 2012 The NetBSD Foundation, Inc. * All rights reserved. @@ -34,7 +34,7 @@ #define _INTR_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.23 2017/06/05 20:02:11 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.24 2017/06/18 22:11:50 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -100,6 +100,7 @@ static struct armgic_softc { #ifdef MULTIPROCESSOR uint32_t sc_mptargets; #endif + uint32_t sc_bptargets; } armgic_softc = { .sc_pic = { .pic_ops = &armgic_picops, @@ -139,6 +140,29 @@ gicd_write(struct armgic_softc *sc, bus_ bus_space_write_4(sc->sc_memt, sc->sc_gicdh, o, v); } +static uint32_t +gicd_find_targets(struct armgic_softc *sc) +{ + uint32_t targets = 0; + + /* + * GICD_ITARGETSR0 through 7 are read-only, and each field returns + * a value that corresponds only to the processor reading the + * register. Use this to determine the current processor's + * CPU interface number. + */ + for (int i = 0; i < 8; i++) { + targets = gicd_read(sc, GICD_ITARGETSRn(i)); + if (targets != 0) + break; + } + targets |= (targets >> 16); + targets |= (targets >> 8); + targets &= 0xff; + + return targets ? targets : 1; +} + /* * In the GIC prioritization scheme, lower numbers have higher priority. * Only write priorities that could be non-secure. @@ -326,7 +350,7 @@ armgic_establish_irq(struct pic_softc *p } else #endif #endif - targets |= 1 << byte_shift; + targets |= sc->sc_bptargets << byte_shift; gicd_write(sc, targets_reg, targets); /* @@ -417,11 +441,11 @@ void armgic_cpu_init(struct pic_softc *pic, struct cpu_info *ci) { struct armgic_softc * const sc = PICTOSOFTC(pic); - sc->sc_mptargets |= 1 << cpu_index(ci); + sc->sc_mptargets |= gicd_find_targets(sc); KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl); armgic_cpu_init_priorities(sc); if (!CPU_IS_PRIMARY(ci)) { - if (sc->sc_mptargets != 1) { + if (popcount(sc->sc_mptargets) != 1) { armgic_cpu_init_targets(sc); } if (sc->sc_enabled_local) { @@ -502,6 +526,11 @@ armgic_attach(device_t parent, device_t u_int priorities = 1 << popcount32(pmr); /* + * Find the boot processor's CPU interface number. + */ + sc->sc_bptargets = gicd_find_targets(sc); + + /* * Let's find out how many real sources we have. */ for (size_t i = 0, group = 0;