Index: sys/arch/arm/broadcom/bcm2835_intr.c =================================================================== RCS file: /cvsroot/src/sys/arch/arm/broadcom/bcm2835_intr.c,v retrieving revision 1.18 diff -u -p -r1.18 bcm2835_intr.c --- sys/arch/arm/broadcom/bcm2835_intr.c 1 Mar 2019 08:05:46 -0000 1.18 +++ sys/arch/arm/broadcom/bcm2835_intr.c 1 Mar 2019 11:29:17 -0000 @@ -40,6 +40,8 @@ __KERNEL_RCSID(0, "$NetBSD: bcm2835_intr #include #include #include +#include +#include #include #include @@ -146,6 +148,20 @@ static struct fdtbus_interrupt_controlle .intrstr = bcm2836mp_icu_fdt_intrstr }; +struct bcm2836mp_interrupt { + bool bi_done; + TAILQ_ENTRY(bcm2836mp_interrupt) bi_next; + int bi_irq; + int bi_ipl; + int bi_flags; + int (*bi_func)(void *); + void *bi_arg; + void *bi_ihs[BCM2836_NCPUS]; +}; + +static TAILQ_HEAD(, bcm2836mp_interrupt) bcm2836mp_interrupts = + TAILQ_HEAD_INITIALIZER(bcm2836mp_interrupts); + struct bcm2835icu_softc { device_t sc_dev; bus_space_tag_t sc_iot; @@ -450,20 +466,19 @@ bcm2835_icu_fdt_intrstr(device_t dev, u_ } #define BCM2836MP_TIMER_IRQS __BITS(3,0) -#define BCM2836MP_MAILBOX_IRQS __BITS(4,4) - -#define BCM2836MP_ALL_IRQS (BCM2836MP_TIMER_IRQS | BCM2836MP_MAILBOX_IRQS) +#define BCM2836MP_MAILBOX_IRQS __BITS(4,7) +#define BCM2836MP_GPU_IRQ __BIT(8) +#define BCM2836MP_PMU_IRQ __BIT(9) +#define BCM2836MP_ALL_IRQS (BCM2836MP_TIMER_IRQS | BCM2836MP_MAILBOX_IRQS | BCM2836MP_GPU_IRQ | BCM2836MP_PMU_IRQ) static void bcm2836mp_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irq_mask) { - struct cpu_info * const ci = curcpu(); - const cpuid_t cpuid = ci->ci_core_id; const bus_space_tag_t iot = bcml1icu_sc->sc_iot; const bus_space_handle_t ioh = bcml1icu_sc->sc_ioh; + const cpuid_t cpuid = pic - &bcm2836mp_pic[0]; - KASSERT(pic == &bcm2836mp_pic[cpuid]); KASSERT(irqbase == 0); if (irq_mask & BCM2836MP_TIMER_IRQS) { @@ -492,6 +507,12 @@ bcm2836mp_pic_unblock_irqs(struct pic_so BCM2836_LOCAL_MAILBOX_IRQ_CONTROL_SIZE, BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE); } + if (irq_mask & BCM2836MP_PMU_IRQ) { + bus_space_write_4(iot, ioh, BCM2836_LOCAL_PM_ROUTING_SET, + __BIT(cpuid)); + bus_space_barrier(iot, ioh, BCM2836_LOCAL_PM_ROUTING_SET, 4, + BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE); + } return; } @@ -500,12 +521,10 @@ static void bcm2836mp_pic_block_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irq_mask) { - struct cpu_info * const ci = curcpu(); - const cpuid_t cpuid = ci->ci_core_id; const bus_space_tag_t iot = bcml1icu_sc->sc_iot; const bus_space_handle_t ioh = bcml1icu_sc->sc_ioh; + const cpuid_t cpuid = pic - &bcm2836mp_pic[0]; - KASSERT(pic == &bcm2836mp_pic[cpuid]); KASSERT(irqbase == 0); if (irq_mask & BCM2836MP_TIMER_IRQS) { @@ -526,6 +545,10 @@ bcm2836mp_pic_block_irqs(struct pic_soft BCM2836_LOCAL_MAILBOX_IRQ_CONTROLN(cpuid), val); } + if (irq_mask & BCM2836MP_PMU_IRQ) { + bus_space_write_4(iot, ioh, BCM2836_LOCAL_PM_ROUTING_CLR, + __BIT(cpuid)); + } bcm2835_barrier(); return; @@ -656,14 +679,19 @@ bcm2836mp_intr_init(void *priv, struct c #if defined(MULTIPROCESSOR) intr_establish(BCM2836_INT_MAILBOX0_CPUN(cpuid), IPL_HIGH, IST_LEVEL | IST_MPSAFE, bcm2836mp_ipi_handler, NULL); -#endif - /* clock interrupt will attach with gtmr */ - if (cpuid == 0) - return; -#if defined(SOC_BCM2836) - intr_establish(BCM2836_INT_CNTVIRQ_CPUN(cpuid), IPL_CLOCK, - IST_LEVEL | IST_MPSAFE, gtmr_intr, NULL); + struct bcm2836mp_interrupt *bip; + TAILQ_FOREACH(bip, &bcm2836mp_interrupts, bi_next) { + if (bip->bi_done) + continue; + + const int irq = BCM2836_INT_BASECPUN(cpuid) + bip->bi_irq; + void *ih = intr_establish(irq, bip->bi_ipl, + IST_LEVEL | bip->bi_flags, bip->bi_func, bip->bi_arg); + +// KASSERTMSG(bip->bi_ihs[cpuid] == NULL, "bip %p bip->bi_ihs[%ld] %p", bip, cpuid, bip->bi_ihs[cpuid]); + bip->bi_ihs[cpuid] = ih; + } #endif } @@ -672,7 +700,7 @@ bcm2836mp_icu_fdt_decode_irq(u_int *spec { if (!specifier) return -1; - return be32toh(specifier[0]) + BCM2836_INT_LOCALBASE; + return be32toh(specifier[0]); } static void * @@ -680,19 +708,91 @@ bcm2836mp_icu_fdt_establish(device_t dev int (*func)(void *), void *arg) { int iflags = (flags & FDT_INTR_MPSAFE) ? IST_MPSAFE : 0; - int irq; + struct bcm2836mp_interrupt *bip; + void *ih; - irq = bcm2836mp_icu_fdt_decode_irq(specifier); + int irq = bcm2836mp_icu_fdt_decode_irq(specifier); if (irq == -1) return NULL; - return intr_establish(irq, ipl, IST_LEVEL | iflags, func, arg); + TAILQ_FOREACH(bip, &bcm2836mp_interrupts, bi_next) { + if (irq == bip->bi_irq) + return NULL; + } + + bip = kmem_alloc(sizeof(*bip), KM_SLEEP); + if (bip == NULL) + return NULL; + + bip->bi_done = false; + bip->bi_irq = irq; + bip->bi_ipl = ipl; + bip->bi_flags = IST_LEVEL | iflags; + bip->bi_func = func; + bip->bi_arg = arg; + + /* + * If we're not cold and the BPs have been started then we can register the + * interupt for all CPUs now, e.g. PMU + */ + if (!cold) { + for (cpuid_t cpuid = 0; cpuid < BCM2836_NCPUS; cpuid++) { + ih = intr_establish(BCM2836_INT_BASECPUN(cpuid) + irq, ipl, + IST_LEVEL | iflags, func, arg); + if (!ih) { + kmem_free(bip, sizeof(*bip)); + return NULL; + } + bip->bi_ihs[cpuid] = ih; + + } + bip->bi_done = true; + ih = bip->bi_ihs[0]; + goto done; + } + + /* + * Otherwise we can only establish the interrupt for the BP and + * delay until bcm2836mp_intr_init is called for each AP, e.g. + * gtmr + */ + + ih = intr_establish(BCM2836_INT_BASECPUN(0) + irq, ipl, + IST_LEVEL | iflags, func, arg); + if (!ih) { + kmem_free(bip, sizeof(*bip)); + return NULL; + } + + bip->bi_ihs[0] = ih; + for (cpuid_t cpuid = 1; cpuid < BCM2836_NCPUS; cpuid++) + bip->bi_ihs[cpuid] = NULL; + +done: + TAILQ_INSERT_TAIL(&bcm2836mp_interrupts, bip, bi_next); + + return ih; } static void bcm2836mp_icu_fdt_disestablish(device_t dev, void *ih) { - intr_disestablish(ih); + struct bcm2836mp_interrupt *bip; + + TAILQ_FOREACH(bip, &bcm2836mp_interrupts, bi_next) { + if (bip->bi_ihs[0] == ih) + break; + } + + if (bip == NULL) + return; + + for (cpuid_t cpuid = 0; cpuid < BCM2836_NCPUS; cpuid++) + intr_disestablish(bip->bi_ihs[cpuid]); + + TAILQ_REMOVE(&bcm2836mp_interrupts, bip, bi_next); + + kmem_free(bip, sizeof(*bip)); } static bool