Home | History | Annotate | Line # | Download | only in broadcom
bcm2835_intr.c revision 1.4.2.2
      1 /*	$NetBSD: bcm2835_intr.c,v 1.4.2.2 2015/06/06 14:39:55 skrll Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2012, 2015 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Nick Hudson
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: bcm2835_intr.c,v 1.4.2.2 2015/06/06 14:39:55 skrll Exp $");
     34 
     35 #define _INTR_PRIVATE
     36 
     37 #include "opt_bcm283x.h"
     38 
     39 #include <sys/param.h>
     40 #include <sys/bus.h>
     41 #include <sys/cpu.h>
     42 #include <sys/device.h>
     43 #include <sys/proc.h>
     44 
     45 #include <machine/intr.h>
     46 
     47 #include <arm/locore.h>
     48 
     49 #include <arm/pic/picvar.h>
     50 #include <arm/cortex/gtmr_var.h>
     51 
     52 #include <arm/broadcom/bcm_amba.h>
     53 #include <arm/broadcom/bcm2835reg.h>
     54 #include <arm/broadcom/bcm2835var.h>
     55 
     56 static void bcm2835_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
     57 static void bcm2835_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
     58 static int bcm2835_pic_find_pending_irqs(struct pic_softc *);
     59 static void bcm2835_pic_establish_irq(struct pic_softc *, struct intrsource *);
     60 static void bcm2835_pic_source_name(struct pic_softc *, int, char *,
     61     size_t);
     62 
     63 #if defined(BCM2836)
     64 static void bcm2836mp_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
     65 static void bcm2836mp_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
     66 static int bcm2836mp_pic_find_pending_irqs(struct pic_softc *);
     67 static void bcm2836mp_pic_establish_irq(struct pic_softc *, struct intrsource *);
     68 static void bcm2836mp_pic_source_name(struct pic_softc *, int, char *,
     69     size_t);
     70 #ifdef MULTIPROCESSOR
     71 int bcm2836mp_ipi_handler(void *);
     72 static void bcm2836mp_cpu_init(struct pic_softc *, struct cpu_info *);
     73 static void bcm2836mp_send_ipi(struct pic_softc *, const kcpuset_t *, u_long);
     74 #endif
     75 #endif
     76 
     77 static int  bcm2835_icu_match(device_t, cfdata_t, void *);
     78 static void bcm2835_icu_attach(device_t, device_t, void *);
     79 
     80 static struct pic_ops bcm2835_picops = {
     81 	.pic_unblock_irqs = bcm2835_pic_unblock_irqs,
     82 	.pic_block_irqs = bcm2835_pic_block_irqs,
     83 	.pic_find_pending_irqs = bcm2835_pic_find_pending_irqs,
     84 	.pic_establish_irq = bcm2835_pic_establish_irq,
     85 	.pic_source_name = bcm2835_pic_source_name,
     86 };
     87 
     88 struct pic_softc bcm2835_pic = {
     89 	.pic_ops = &bcm2835_picops,
     90 	.pic_maxsources = BCM2835_NIRQ,
     91 	.pic_name = "bcm2835 pic",
     92 };
     93 
     94 #if defined(BCM2836)
     95 static struct pic_ops bcm2836mp_picops = {
     96 	.pic_unblock_irqs = bcm2836mp_pic_unblock_irqs,
     97 	.pic_block_irqs = bcm2836mp_pic_block_irqs,
     98 	.pic_find_pending_irqs = bcm2836mp_pic_find_pending_irqs,
     99 	.pic_establish_irq = bcm2836mp_pic_establish_irq,
    100 	.pic_source_name = bcm2836mp_pic_source_name,
    101 #if defined(MULTIPROCESSOR)
    102 	.pic_cpu_init = bcm2836mp_cpu_init,
    103 	.pic_ipi_send = bcm2836mp_send_ipi,
    104 #endif
    105 };
    106 
    107 struct pic_softc bcm2836mp_pic[BCM2836_NCPUS] = {
    108 	[0] = {
    109 		.pic_ops = &bcm2836mp_picops,
    110 		.pic_maxsources = BCM2836_NIRQPERCPU,
    111 		.pic_name = "bcm2836 pic",
    112 	},
    113 	[1] = {
    114 		.pic_ops = &bcm2836mp_picops,
    115 		.pic_maxsources = BCM2836_NIRQPERCPU,
    116 		.pic_name = "bcm2836 pic",
    117 	},
    118 	[2] = {
    119 		.pic_ops = &bcm2836mp_picops,
    120 		.pic_maxsources = BCM2836_NIRQPERCPU,
    121 		.pic_name = "bcm2836 pic",
    122 	},
    123 	[3] = {
    124 		.pic_ops = &bcm2836mp_picops,
    125 		.pic_maxsources = BCM2836_NIRQPERCPU,
    126 		.pic_name = "bcm2836 pic",
    127 	},
    128 };
    129 #endif
    130 
    131 struct bcm2835icu_softc {
    132 	device_t		sc_dev;
    133 	bus_space_tag_t		sc_iot;
    134 	bus_space_handle_t	sc_ioh;
    135 	struct pic_softc	*sc_pic;
    136 };
    137 
    138 struct bcm2835icu_softc *bcmicu_sc;
    139 
    140 #define read_bcm2835reg(o)	\
    141 	bus_space_read_4(bcmicu_sc->sc_iot, bcmicu_sc->sc_ioh, (o))
    142 
    143 #define write_bcm2835reg(o, v)	\
    144 	bus_space_write_4(bcmicu_sc->sc_iot, bcmicu_sc->sc_ioh, (o), (v))
    145 
    146 
    147 #define bcm2835_barrier() \
    148 	bus_space_barrier(bcmicu_sc->sc_iot, bcmicu_sc->sc_ioh, 0, \
    149 	    BCM2835_ARMICU_SIZE, BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE)
    150 
    151 static const char * const bcm2835_sources[BCM2835_NIRQ] = {
    152 	"(unused  0)",	"(unused  1)",	"(unused  2)",	"timer3",
    153 	"(unused  4)",	"(unused  5)",	"(unused  6)",	"jpeg",
    154 	"(unused  8)",	"usb",		"(unused 10)",	"(unused 11)",
    155 	"(unused 12)",	"(unused 13)",	"(unused 14)",	"(unused 15)",
    156 	"dma0",		"dma1",		"dma2",		"dma3",
    157 	"dma4",		"dma5",		"dma6",		"dma7",
    158 	"dma8",		"dma9",		"dma10",	"dma11",
    159 	"dma12",	"aux",		"(unused 30)",	"(unused 31)",
    160 	"(unused 32)",	"(unused 33)",	"(unused 34)",	"(unused 35)",
    161 	"(unused 36)",	"(unused 37)",	"(unused 38)",	"(unused 39)",
    162 	"(unused 40)",	"(unused 41)",	"(unused 42)",	"i2c spl slv",
    163 	"(unused 44)",	"pwa0",		"pwa1",		"(unused 47)",
    164 	"smi",		"gpio[0]",	"gpio[1]",	"gpio[2]",
    165 	"gpio[3]",	"i2c",		"spi",		"pcm",
    166 	"sdio",		"uart",		"(unused 58)",	"(unused 59)",
    167 	"(unused 60)",	"(unused 61)",	"emmc",		"(unused 63)",
    168 	"Timer",	"Mailbox",	"Doorbell0",	"Doorbell1",
    169 	"GPU0 Halted",	"GPU1 Halted",	"Illegal #1",	"Illegal #0"
    170 };
    171 
    172 #if defined(BCM2836)
    173 static const char * const bcm2836mp_sources[BCM2836_NIRQPERCPU] = {
    174 	"cntpsirq",	"cntpnsirq",	"cnthpirq",	"cntvirq",
    175 	"mailbox0",	"mailbox1",	"mailbox2",	"mailbox3",
    176 };
    177 #endif
    178 
    179 #define	BCM2836_INTBIT_GPUPENDING	__BIT(8)
    180 
    181 #define	BCM2835_INTBIT_PENDING1		__BIT(8)
    182 #define	BCM2835_INTBIT_PENDING2		__BIT(9)
    183 #define	BCM2835_INTBIT_ARM		__BITS(0,7)
    184 #define	BCM2835_INTBIT_GPU0		__BITS(10,14)
    185 #define	BCM2835_INTBIT_GPU1		__BITS(15,20)
    186 
    187 CFATTACH_DECL_NEW(bcmicu, sizeof(struct bcm2835icu_softc),
    188     bcm2835_icu_match, bcm2835_icu_attach, NULL, NULL);
    189 
    190 static int
    191 bcm2835_icu_match(device_t parent, cfdata_t cf, void *aux)
    192 {
    193 	struct amba_attach_args *aaa = aux;
    194 
    195 	if (strcmp(aaa->aaa_name, "icu") != 0)
    196 		return 0;
    197 
    198 	return 1;
    199 }
    200 
    201 static void
    202 bcm2835_icu_attach(device_t parent, device_t self, void *aux)
    203 {
    204 	struct bcm2835icu_softc *sc = device_private(self);
    205 	struct amba_attach_args *aaa = aux;
    206 
    207 	sc->sc_dev = self;
    208 	sc->sc_iot = aaa->aaa_iot;
    209 	sc->sc_pic = &bcm2835_pic;
    210 
    211 	if (bus_space_map(aaa->aaa_iot, aaa->aaa_addr, aaa->aaa_size, 0,
    212 	    &sc->sc_ioh)) {
    213 		aprint_error_dev(self, "unable to map device\n");
    214 		return;
    215 	}
    216 
    217 	bcmicu_sc = sc;
    218 
    219 #if defined(BCM2836)
    220 #if defined(MULTIPROCESSOR)
    221 	aprint_normal(": Multiprocessor");
    222 #endif
    223 
    224 	bcm2836mp_intr_init(curcpu());
    225 #endif
    226 	pic_add(sc->sc_pic, BCM2835_INT_BASE);
    227 
    228 	aprint_normal("\n");
    229 }
    230 
    231 void
    232 bcm2835_irq_handler(void *frame)
    233 {
    234 	struct cpu_info * const ci = curcpu();
    235 	const int oldipl = ci->ci_cpl;
    236 	const cpuid_t cpuid = ci->ci_cpuid;
    237 	const uint32_t oldipl_mask = __BIT(oldipl);
    238 	int ipl_mask = 0;
    239 
    240 	ci->ci_data.cpu_nintr++;
    241 
    242 	bcm2835_barrier();
    243 	if (cpuid == 0) {
    244 		ipl_mask = bcm2835_pic_find_pending_irqs(&bcm2835_pic);
    245 	}
    246 #if defined(BCM2836)
    247 	ipl_mask |= bcm2836mp_pic_find_pending_irqs(&bcm2836mp_pic[cpuid]);
    248 #endif
    249 
    250 	/*
    251 	 * Record the pending_ipls and deliver them if we can.
    252 	 */
    253 	if ((ipl_mask & ~oldipl_mask) > oldipl_mask)
    254 		pic_do_pending_ints(I32_bit, oldipl, frame);
    255 }
    256 
    257 static void
    258 bcm2835_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
    259     uint32_t irq_mask)
    260 {
    261 
    262 	write_bcm2835reg(BCM2835_INTC_ENABLEBASE + (irqbase >> 3), irq_mask);
    263 	bcm2835_barrier();
    264 }
    265 
    266 static void
    267 bcm2835_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
    268     uint32_t irq_mask)
    269 {
    270 
    271 	write_bcm2835reg(BCM2835_INTC_DISABLEBASE + (irqbase >> 3), irq_mask);
    272 	bcm2835_barrier();
    273 }
    274 
    275 /*
    276  * Called with interrupts disabled
    277  */
    278 static int
    279 bcm2835_pic_find_pending_irqs(struct pic_softc *pic)
    280 {
    281 	int ipl = 0;
    282 	uint32_t bpending, gpu0irq, gpu1irq, armirq;
    283 
    284 	bcm2835_barrier();
    285 	bpending = read_bcm2835reg(BCM2835_INTC_IRQBPENDING);
    286 	if (bpending == 0)
    287 		return 0;
    288 
    289 	armirq = bpending & BCM2835_INTBIT_ARM;
    290 	gpu0irq = bpending & BCM2835_INTBIT_GPU0;
    291 	gpu1irq = bpending & BCM2835_INTBIT_GPU1;
    292 
    293 	if (armirq) {
    294 		ipl |= pic_mark_pending_sources(pic,
    295 		    BCM2835_INT_BASICBASE - BCM2835_INT_BASE, armirq);
    296 
    297 	}
    298 
    299 	if (gpu0irq || (bpending & BCM2835_INTBIT_PENDING1)) {
    300 		uint32_t pending1;
    301 
    302 		pending1 = read_bcm2835reg(BCM2835_INTC_IRQ1PENDING);
    303 		ipl |= pic_mark_pending_sources(pic,
    304 		    BCM2835_INT_GPU0BASE - BCM2835_INT_BASE, pending1);
    305 	}
    306 	if (gpu1irq || (bpending & BCM2835_INTBIT_PENDING2)) {
    307 		uint32_t pending2;
    308 
    309 		pending2 = read_bcm2835reg(BCM2835_INTC_IRQ2PENDING);
    310 		ipl |= pic_mark_pending_sources(pic,
    311 		    BCM2835_INT_GPU1BASE - BCM2835_INT_BASE, pending2);
    312 	}
    313 
    314 	return ipl;
    315 }
    316 
    317 static void
    318 bcm2835_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
    319 {
    320 
    321 	/* Nothing really*/
    322 	KASSERT(is->is_irq < BCM2835_NIRQ);
    323 	KASSERT(is->is_type == IST_LEVEL);
    324 }
    325 
    326 static void
    327 bcm2835_pic_source_name(struct pic_softc *pic, int irq, char *buf, size_t len)
    328 {
    329 
    330 	strlcpy(buf, bcm2835_sources[irq], len);
    331 }
    332 
    333 
    334 #if defined(BCM2836)
    335 
    336 #define	BCM2836MP_TIMER_IRQS	__BITS(3,0)
    337 #define	BCM2836MP_MAILBOX_IRQS	__BITS(4,4)
    338 
    339 #define	BCM2836MP_ALL_IRQS	\
    340     (BCM2836MP_TIMER_IRQS | BCM2836MP_MAILBOX_IRQS)
    341 
    342 static void
    343 bcm2836mp_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
    344     uint32_t irq_mask)
    345 {
    346 	struct cpu_info * const ci = curcpu();
    347 	const cpuid_t cpuid = ci->ci_cpuid;
    348 
    349 	KASSERT(pic == &bcm2836mp_pic[cpuid]);
    350 	KASSERT(irqbase == 0);
    351 
    352 	if (irq_mask & BCM2836MP_TIMER_IRQS) {
    353 		uint32_t mask = __SHIFTOUT(irq_mask, BCM2836MP_TIMER_IRQS);
    354 		uint32_t val = bus_space_read_4(al_iot, al_ioh,
    355 		    BCM2836_LOCAL_TIMER_IRQ_CONTROLN(cpuid));
    356 		val |= mask;
    357 		bus_space_write_4(al_iot, al_ioh,
    358 		    BCM2836_LOCAL_TIMER_IRQ_CONTROLN(cpuid),
    359 		    val);
    360 		bus_space_barrier(al_iot, al_ioh,
    361 		    BCM2836_LOCAL_TIMER_IRQ_CONTROL_BASE,
    362 		    BCM2836_LOCAL_TIMER_IRQ_CONTROL_SIZE,
    363 		    BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
    364 	} else if (irq_mask & BCM2836MP_MAILBOX_IRQS) {
    365 		uint32_t mask = __SHIFTOUT(irq_mask, BCM2836MP_MAILBOX_IRQS);
    366 		uint32_t val = bus_space_read_4(al_iot, al_ioh,
    367 		    BCM2836_LOCAL_MAILBOX_IRQ_CONTROLN(cpuid));
    368 		val |= mask;
    369 		bus_space_write_4(al_iot, al_ioh,
    370 		    BCM2836_LOCAL_MAILBOX_IRQ_CONTROLN(cpuid),
    371 		    val);
    372 		bus_space_barrier(al_iot, al_ioh,
    373 		    BCM2836_LOCAL_MAILBOX_IRQ_CONTROL_BASE,
    374 		    BCM2836_LOCAL_MAILBOX_IRQ_CONTROL_SIZE,
    375 		    BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
    376 	}
    377 
    378 	return;
    379 }
    380 
    381 static void
    382 bcm2836mp_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
    383     uint32_t irq_mask)
    384 {
    385 	struct cpu_info * const ci = curcpu();
    386 	const cpuid_t cpuid = ci->ci_cpuid;
    387 
    388 	KASSERT(pic == &bcm2836mp_pic[cpuid]);
    389 	KASSERT(irqbase == 0);
    390 
    391 	if (irq_mask & BCM2836MP_TIMER_IRQS) {
    392 		uint32_t mask = __SHIFTOUT(irq_mask, BCM2836MP_TIMER_IRQS);
    393 		uint32_t val = bus_space_read_4(al_iot, al_ioh,
    394 		    BCM2836_LOCAL_TIMER_IRQ_CONTROLN(cpuid));
    395 		val &= ~mask;
    396 		bus_space_write_4(al_iot, al_ioh,
    397 		    BCM2836_LOCAL_TIMER_IRQ_CONTROLN(cpuid),
    398 		    val);
    399 	} else if (irq_mask & BCM2836MP_MAILBOX_IRQS) {
    400 		uint32_t mask = __SHIFTOUT(irq_mask, BCM2836MP_MAILBOX_IRQS);
    401 		uint32_t val = bus_space_read_4(al_iot, al_ioh,
    402 		    BCM2836_LOCAL_MAILBOX_IRQ_CONTROLN(cpuid));
    403 		val &= ~mask;
    404 		bus_space_write_4(al_iot, al_ioh,
    405 		    BCM2836_LOCAL_MAILBOX_IRQ_CONTROLN(cpuid),
    406 		    val);
    407 	}
    408 
    409 	bcm2835_barrier();
    410 	return;
    411 }
    412 
    413 static int
    414 bcm2836mp_pic_find_pending_irqs(struct pic_softc *pic)
    415 {
    416 	struct cpu_info * const ci = curcpu();
    417 	const cpuid_t cpuid = ci->ci_cpuid;
    418 	uint32_t lpending;
    419 	int ipl = 0;
    420 
    421 	KASSERT(pic == &bcm2836mp_pic[cpuid]);
    422 
    423 	bcm2835_barrier();
    424 
    425 	lpending = bus_space_read_4(al_iot, al_ioh,
    426 	    BCM2836_LOCAL_INTC_IRQPENDINGN(cpuid));
    427 
    428 	lpending &= ~BCM2836_INTBIT_GPUPENDING;
    429 	if (lpending & BCM2836MP_ALL_IRQS) {
    430 		ipl |= pic_mark_pending_sources(pic, 0 /* BCM2836_INT_LOCALBASE */,
    431 		    lpending & BCM2836MP_ALL_IRQS);
    432 	}
    433 
    434 	return ipl;
    435 }
    436 
    437 static void
    438 bcm2836mp_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
    439 {
    440 	/* Nothing really*/
    441 	KASSERT(is->is_irq >= 0);
    442 	KASSERT(is->is_irq < BCM2836_NIRQPERCPU);
    443 }
    444 
    445 static void
    446 bcm2836mp_pic_source_name(struct pic_softc *pic, int irq, char *buf, size_t len)
    447 {
    448 
    449 	irq %= BCM2836_NIRQPERCPU;
    450 	strlcpy(buf, bcm2836mp_sources[irq], len);
    451 }
    452 
    453 
    454 #ifdef MULTIPROCESSOR
    455 static void bcm2836mp_cpu_init(struct pic_softc *pic, struct cpu_info *ci)
    456 {
    457 
    458 	/* Enable IRQ and not FIQ */
    459 	bus_space_write_4(al_iot, al_ioh,
    460 	    BCM2836_LOCAL_MAILBOX_IRQ_CONTROLN(ci->ci_cpuid), 1);
    461 }
    462 
    463 
    464 static void
    465 bcm2836mp_send_ipi(struct pic_softc *pic, const kcpuset_t *kcp, u_long ipi)
    466 {
    467 	const cpuid_t cpuid = pic - &bcm2836mp_pic[0];
    468 
    469 	bus_space_write_4(al_iot, al_ioh,
    470 	    BCM2836_LOCAL_MAILBOX0_SETN(cpuid), __BIT(ipi));
    471 }
    472 
    473 int
    474 bcm2836mp_ipi_handler(void *priv)
    475 {
    476 	const struct cpu_info *ci = curcpu();
    477 	const cpuid_t cpuid = ci->ci_cpuid;
    478 	uint32_t ipimask, bit;
    479 
    480 	ipimask = bus_space_read_4(al_iot, al_ioh,
    481 	    BCM2836_LOCAL_MAILBOX0_CLRN(cpuid));
    482 	bus_space_write_4(al_iot, al_ioh, BCM2836_LOCAL_MAILBOX0_CLRN(cpuid),
    483 	    ipimask);
    484 
    485 	while ((bit = ffs(ipimask)) > 0) {
    486 		const u_int ipi = bit - 1;
    487 		switch (ipi) {
    488 		case IPI_AST:
    489 		case IPI_NOP:
    490 #ifdef __HAVE_PREEMPTION
    491 		case IPI_KPREEMPT:
    492 #endif
    493 			pic_ipi_nop(priv);
    494 			break;
    495 		case IPI_XCALL:
    496 			pic_ipi_xcall(priv);
    497 			break;
    498 		case IPI_GENERIC:
    499 			pic_ipi_generic(priv);
    500 			break;
    501 		case IPI_SHOOTDOWN:
    502 			pic_ipi_shootdown(priv);
    503 			break;
    504 #ifdef DDB
    505 		case IPI_DDB:
    506 			pic_ipi_ddb(priv);
    507 			break;
    508 #endif
    509 		}
    510 		ipimask &= ~__BIT(ipi);
    511 	}
    512 
    513 	return 1;
    514 }
    515 
    516 void
    517 bcm2836mp_intr_init(struct cpu_info *ci)
    518 {
    519 	const cpuid_t cpuid = ci->ci_cpuid;
    520 	struct pic_softc * const pic = &bcm2836mp_pic[cpuid];
    521 
    522 	pic->pic_cpus = ci->ci_kcpuset;
    523 	pic_add(pic, BCM2836_INT_BASECPUN(cpuid));
    524 
    525 	intr_establish(BCM2836_INT_MAILBOX0_CPUN(cpuid), IPL_VM,
    526 	    IST_LEVEL | IST_MPSAFE, bcm2836mp_ipi_handler, NULL);
    527 
    528 	/* clock interrupt will attach with gtmr */
    529 	if (cpuid == 0)
    530 		return;
    531 
    532 	intr_establish(BCM2836_INT_CNTVIRQ_CPUN(cpuid), IPL_CLOCK,
    533 	    IST_LEVEL | IST_MPSAFE, gtmr_intr, NULL);
    534 
    535 }
    536 #endif
    537 
    538 #endif
    539