Index: sys/arch/arm/cortex/gic.c =================================================================== RCS file: /cvsroot/src/sys/arch/arm/cortex/gic.c,v retrieving revision 1.28 diff -u -p -r1.28 gic.c --- sys/arch/arm/cortex/gic.c 22 Jun 2017 08:10:29 -0000 1.28 +++ sys/arch/arm/cortex/gic.c 26 Jun 2017 12:38:49 -0000 @@ -419,7 +419,7 @@ armgic_establish_irq(struct pic_softc *p * All group 0 interrupts are per processor and MPSAFE by * default. */ - is->is_mpsafe = true; + KASSERT(is->is_mpsafe); #endif } @@ -434,10 +434,48 @@ armgic_establish_irq(struct pic_softc *p gicd_write(sc, priority_reg, priority); } + +static void +armgic_dist_init(struct armgic_softc *sc) +{ + KERNHIST_FUNC(__func__); KERNHIST_CALLED(armgichist); + + // Distributer should be disabled + KASSERT(!(gicd_read(sc, GICD_CTRL) & GICD_CTRL_Enable)); + + for (size_t i = 32; i < sc->sc_pic.pic_maxsources; i += 4) { + // Target all SPIs at no CPUs. + if ((i % 4) == 0) + gicd_write(sc, GICD_ITARGETSRn(i / 4), 0); + // Set all SPIs to level triggered, active low + if ((i % 16) == 0) + gicd_write(sc, GICD_ICFGRn(i / 16), 0); + // Clear pending for all SPIs + if ((i % 32) == 0) { + //gicd_write(sc, GICD_ICENABLERn(i / 32, 0xffffffff); + gicd_write(sc, GICD_ICPENDRn(i / 32), ~0); + } + } + /* + * Force the GICD to IPL_HIGH and then enable interrupts. + */ + struct cpu_info * const ci = curcpu(); + KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl); + armgic_set_priority(&sc->sc_pic, ci->ci_cpl); // set PMR + gicd_write(sc, GICD_CTRL, GICD_CTRL_Enable); // enable Distributer + gicc_write(sc, GICC_CTRL, GICC_CTRL_V1_Enable); // enable CPU interrupts + cpsie(I32_bit); // allow interrupt exceptions +} + #ifdef MULTIPROCESSOR static void -armgic_cpu_init_priorities(struct armgic_softc *sc) +armgic_cpuif_init(struct armgic_softc *sc) { + KERNHIST_FUNC(__func__); KERNHIST_CALLED(armgichist); + + // Clear pending for all SPIs/PPIs + gicd_write(sc, GICD_ICPENDRn(0), ~0); + /* Set lowest priority, i.e. disable interrupts */ for (size_t i = 0; i < 32; i += 4) { const bus_size_t priority_reg = GICD_IPRIORITYRn(i / 4); @@ -446,7 +484,7 @@ armgic_cpu_init_priorities(struct armgic } static void -armgic_cpu_update_priorities(struct armgic_softc *sc) +armgic_cpuif_update_priorities(struct armgic_softc *sc) { uint32_t enabled = sc->sc_enabled_local; for (size_t i = 0; i < 32; i += 4, enabled >>= 4) { @@ -467,7 +505,7 @@ armgic_cpu_update_priorities(struct armg } static void -armgic_cpu_init_targets(struct armgic_softc *sc) +armgic_cpuif_init_targets(struct armgic_softc *sc) { /* * Update the mpsafe targets @@ -488,15 +526,25 @@ void armgic_cpu_init(struct pic_softc *pic, struct cpu_info *ci) { struct armgic_softc * const sc = PICTOSOFTC(pic); + + uint32_t iidr = gicc_read(sc, GICC_IIDR); + int iidr_prod = __SHIFTOUT(iidr, GICC_IIDR_ProductID); + int iidr_arch = __SHIFTOUT(iidr, GICC_IIDR_ArchVersion); + int iidr_rev = __SHIFTOUT(iidr, GICC_IIDR_Revision); + int iidr_imp = __SHIFTOUT(iidr, GICC_IIDR_Implementer); + + aprint_verbose_dev(sc->sc_dev, "CPU Interface Architecture version %d" + " (0x%x:%d rev %d)\n", iidr_arch, iidr_imp, iidr_prod, iidr_rev); + 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); + armgic_cpuif_init(sc); if (!CPU_IS_PRIMARY(ci)) { if (popcount(sc->sc_mptargets) != 1) { - armgic_cpu_init_targets(sc); + armgic_cpuif_init_targets(sc); } if (sc->sc_enabled_local) { - armgic_cpu_update_priorities(sc); + armgic_cpuif_update_priorities(sc); gicd_write(sc, GICD_ISENABLERn(0), sc->sc_enabled_local); } @@ -630,15 +678,7 @@ armgic_attach(device_t parent, device_t #endif pic_add(&sc->sc_pic, 0); - /* - * Force the GICD to IPL_HIGH and then enable interrupts. - */ - struct cpu_info * const ci = curcpu(); - KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl); - armgic_set_priority(&sc->sc_pic, ci->ci_cpl); // set PMR - gicd_write(sc, GICD_CTRL, GICD_CTRL_Enable); // enable Distributer - gicc_write(sc, GICC_CTRL, GICC_CTRL_V1_Enable); // enable CPU interrupts - cpsie(I32_bit); // allow interrupt exceptions + armgic_dist_init(sc); /* * For each line that isn't valid, we set the intrsource for it to