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