Home | History | Annotate | Line # | Download | only in broadcom
bcm2835_intr.c revision 1.1.2.4
      1  1.1.2.4  riz /*	$NetBSD: bcm2835_intr.c,v 1.1.2.4 2013/02/13 01:36:14 riz Exp $	*/
      2  1.1.2.2  jdc 
      3  1.1.2.2  jdc /*-
      4  1.1.2.2  jdc  * Copyright (c) 2012 The NetBSD Foundation, Inc.
      5  1.1.2.2  jdc  * All rights reserved.
      6  1.1.2.2  jdc  *
      7  1.1.2.2  jdc  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1.2.2  jdc  * by Nick Hudson
      9  1.1.2.2  jdc  *
     10  1.1.2.2  jdc  * Redistribution and use in source and binary forms, with or without
     11  1.1.2.2  jdc  * modification, are permitted provided that the following conditions
     12  1.1.2.2  jdc  * are met:
     13  1.1.2.2  jdc  * 1. Redistributions of source code must retain the above copyright
     14  1.1.2.2  jdc  *    notice, this list of conditions and the following disclaimer.
     15  1.1.2.2  jdc  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1.2.2  jdc  *    notice, this list of conditions and the following disclaimer in the
     17  1.1.2.2  jdc  *    documentation and/or other materials provided with the distribution.
     18  1.1.2.2  jdc  *
     19  1.1.2.2  jdc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.1.2.2  jdc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.1.2.2  jdc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.1.2.2  jdc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.1.2.2  jdc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.1.2.2  jdc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.1.2.2  jdc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.1.2.2  jdc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.1.2.2  jdc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.1.2.2  jdc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.1.2.2  jdc  * POSSIBILITY OF SUCH DAMAGE.
     30  1.1.2.2  jdc  */
     31  1.1.2.2  jdc 
     32  1.1.2.2  jdc #include <sys/cdefs.h>
     33  1.1.2.4  riz __KERNEL_RCSID(0, "$NetBSD: bcm2835_intr.c,v 1.1.2.4 2013/02/13 01:36:14 riz Exp $");
     34  1.1.2.2  jdc 
     35  1.1.2.2  jdc #define _INTR_PRIVATE
     36  1.1.2.2  jdc 
     37  1.1.2.2  jdc #include <sys/param.h>
     38  1.1.2.2  jdc #include <sys/proc.h>
     39  1.1.2.2  jdc #include <sys/device.h>
     40  1.1.2.2  jdc 
     41  1.1.2.2  jdc #include <machine/intr.h>
     42  1.1.2.2  jdc #include <sys/bus.h>
     43  1.1.2.2  jdc 
     44  1.1.2.2  jdc #include <arm/pic/picvar.h>
     45  1.1.2.2  jdc 
     46  1.1.2.2  jdc #include <arm/broadcom/bcm_amba.h>
     47  1.1.2.2  jdc #include <arm/broadcom/bcm2835reg.h>
     48  1.1.2.2  jdc 
     49  1.1.2.2  jdc static void bcm2835_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
     50  1.1.2.2  jdc static void bcm2835_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
     51  1.1.2.2  jdc static int bcm2835_pic_find_pending_irqs(struct pic_softc *);
     52  1.1.2.2  jdc static void bcm2835_pic_establish_irq(struct pic_softc *, struct intrsource *);
     53  1.1.2.2  jdc static void bcm2835_pic_source_name(struct pic_softc *, int, char *,
     54  1.1.2.2  jdc     size_t);
     55  1.1.2.2  jdc 
     56  1.1.2.2  jdc static int  bcm2835_icu_match(device_t, cfdata_t, void *);
     57  1.1.2.2  jdc static void bcm2835_icu_attach(device_t, device_t, void *);
     58  1.1.2.2  jdc 
     59  1.1.2.2  jdc static struct pic_ops bcm2835_picops = {
     60  1.1.2.2  jdc 	.pic_unblock_irqs = bcm2835_pic_unblock_irqs,
     61  1.1.2.2  jdc 	.pic_block_irqs = bcm2835_pic_block_irqs,
     62  1.1.2.2  jdc 	.pic_find_pending_irqs = bcm2835_pic_find_pending_irqs,
     63  1.1.2.2  jdc 	.pic_establish_irq = bcm2835_pic_establish_irq,
     64  1.1.2.2  jdc 	.pic_source_name = bcm2835_pic_source_name,
     65  1.1.2.2  jdc };
     66  1.1.2.2  jdc 
     67  1.1.2.2  jdc struct pic_softc bcm2835_pic = {
     68  1.1.2.2  jdc 	.pic_ops = &bcm2835_picops,
     69  1.1.2.2  jdc 	.pic_maxsources = BCM2835_NIRQ,
     70  1.1.2.2  jdc 	.pic_name = "bcm2835 pic",
     71  1.1.2.2  jdc };
     72  1.1.2.2  jdc 
     73  1.1.2.2  jdc struct bcm2835icu_softc {
     74  1.1.2.2  jdc 	device_t		sc_dev;
     75  1.1.2.2  jdc 	bus_space_tag_t		sc_iot;
     76  1.1.2.2  jdc 	bus_space_handle_t	sc_ioh;
     77  1.1.2.2  jdc 	struct pic_softc	*sc_pic;
     78  1.1.2.2  jdc };
     79  1.1.2.2  jdc 
     80  1.1.2.2  jdc struct bcm2835icu_softc *bcmicu_sc;
     81  1.1.2.4  riz 
     82  1.1.2.2  jdc #define read_bcm2835reg(o)	\
     83  1.1.2.2  jdc 	bus_space_read_4(bcmicu_sc->sc_iot, bcmicu_sc->sc_ioh, (o))
     84  1.1.2.4  riz 
     85  1.1.2.2  jdc #define write_bcm2835reg(o, v)	\
     86  1.1.2.2  jdc 	bus_space_write_4(bcmicu_sc->sc_iot, bcmicu_sc->sc_ioh, (o), (v))
     87  1.1.2.2  jdc 
     88  1.1.2.2  jdc #define bcm2835_barrier() \
     89  1.1.2.2  jdc 	bus_space_barrier(bcmicu_sc->sc_iot, bcmicu_sc->sc_ioh, 0, \
     90  1.1.2.2  jdc 	    BCM2835_ARMICU_SIZE, BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE)
     91  1.1.2.4  riz 
     92  1.1.2.2  jdc static const char * const bcm2835_sources[BCM2835_NIRQ] = {
     93  1.1.2.2  jdc 	"(unused  0)",	"(unused  1)",	"(unused  2)",	"timer3",
     94  1.1.2.2  jdc 	"(unused  4)",	"(unused  5)",	"(unused  6)",	"jpeg",
     95  1.1.2.3  riz 	"(unused  8)",	"usb",		"(unused 10)",	"(unused 11)",
     96  1.1.2.3  riz 	"(unused 12)",	"(unused 13)",	"(unused 14)",	"(unused 15)",
     97  1.1.2.2  jdc 	"(unused 16)",	"(unused 17)",	"dma2",		"dma3",
     98  1.1.2.2  jdc 	"(unused 20)",	"(unused 21)",	"(unused 22)",	"(unused 23)",
     99  1.1.2.2  jdc 	"(unused 24)",	"(unused 25)",	"(unused 26)",	"(unused 27)",
    100  1.1.2.2  jdc 	"(unused 28)",	"aux",		"(unused 30)",	"(unused 31)",
    101  1.1.2.2  jdc 	"(unused 32)",	"(unused 33)",	"(unused 34)",	"(unused 35)",
    102  1.1.2.2  jdc 	"(unused 36)",	"(unused 37)",	"(unused 38)",	"(unused 39)",
    103  1.1.2.2  jdc 	"(unused 40)",	"(unused 41)",	"(unused 42)",	"i2c spl slv",
    104  1.1.2.2  jdc 	"(unused 44)",	"pwa0",		"pwa1",		"(unused 47)",
    105  1.1.2.2  jdc 	"smi",		"gpio[0]",	"gpio[1]",	"gpio[2]",
    106  1.1.2.2  jdc 	"gpio[3]",	"i2c",		"spi",		"pcm",
    107  1.1.2.2  jdc 	"sdio",		"uart",		"(unused 58)",	"(unused 59)",
    108  1.1.2.2  jdc 	"(unused 60)",	"(unused 61)",	"emmc",		"(unused 63)",
    109  1.1.2.2  jdc 	"Timer",	"Mailbox",	"Doorbell0",	"Doorbell1",
    110  1.1.2.2  jdc 	"GPU0 Halted",	"GPU1 Halted",	"Illegal #1",	"Illegal #0"
    111  1.1.2.2  jdc };
    112  1.1.2.2  jdc 
    113  1.1.2.2  jdc #define	BCM2835_INTBIT_PENDING1		__BIT(8)
    114  1.1.2.2  jdc #define	BCM2835_INTBIT_PENDING2		__BIT(9)
    115  1.1.2.2  jdc #define	BCM2835_INTBIT_ARM		__BITS(0,7)
    116  1.1.2.2  jdc #define	BCM2835_INTBIT_GPU0		__BITS(10,14)
    117  1.1.2.2  jdc #define	BCM2835_INTBIT_GPU1		__BITS(15,20)
    118  1.1.2.2  jdc 
    119  1.1.2.2  jdc CFATTACH_DECL_NEW(bcmicu, sizeof(struct bcm2835icu_softc),
    120  1.1.2.2  jdc     bcm2835_icu_match, bcm2835_icu_attach, NULL, NULL);
    121  1.1.2.2  jdc 
    122  1.1.2.2  jdc static int
    123  1.1.2.2  jdc bcm2835_icu_match(device_t parent, cfdata_t cf, void *aux)
    124  1.1.2.2  jdc {
    125  1.1.2.2  jdc 	struct amba_attach_args *aaa = aux;
    126  1.1.2.2  jdc 
    127  1.1.2.2  jdc 	if (strcmp(aaa->aaa_name, "icu") != 0)
    128  1.1.2.2  jdc 		return 0;
    129  1.1.2.2  jdc 
    130  1.1.2.2  jdc 	return 1;
    131  1.1.2.2  jdc }
    132  1.1.2.2  jdc 
    133  1.1.2.2  jdc static void
    134  1.1.2.2  jdc bcm2835_icu_attach(device_t parent, device_t self, void *aux)
    135  1.1.2.2  jdc {
    136  1.1.2.2  jdc 	struct bcm2835icu_softc *sc = device_private(self);
    137  1.1.2.2  jdc 	struct amba_attach_args *aaa = aux;
    138  1.1.2.2  jdc 
    139  1.1.2.2  jdc 	sc->sc_dev = self;
    140  1.1.2.2  jdc 	sc->sc_iot = aaa->aaa_iot;
    141  1.1.2.2  jdc 	sc->sc_pic = &bcm2835_pic;
    142  1.1.2.2  jdc 
    143  1.1.2.2  jdc 	if (bus_space_map(aaa->aaa_iot, aaa->aaa_addr, aaa->aaa_size, 0,
    144  1.1.2.2  jdc 	    &sc->sc_ioh)) {
    145  1.1.2.2  jdc 		aprint_error_dev(self, "unable to map device\n");
    146  1.1.2.2  jdc 		return;
    147  1.1.2.2  jdc 	}
    148  1.1.2.2  jdc 
    149  1.1.2.2  jdc 	bcmicu_sc = sc;
    150  1.1.2.2  jdc 	pic_add(sc->sc_pic, 0);
    151  1.1.2.2  jdc 	aprint_normal("\n");
    152  1.1.2.2  jdc }
    153  1.1.2.2  jdc 
    154  1.1.2.2  jdc void
    155  1.1.2.2  jdc bcm2835_irq_handler(void *frame)
    156  1.1.2.2  jdc {
    157  1.1.2.2  jdc 	struct cpu_info * const ci = curcpu();
    158  1.1.2.2  jdc 	const int oldipl = ci->ci_cpl;
    159  1.1.2.2  jdc 	const uint32_t oldipl_mask = __BIT(oldipl);
    160  1.1.2.2  jdc 	int ipl_mask = 0;
    161  1.1.2.2  jdc 
    162  1.1.2.2  jdc 	ci->ci_data.cpu_nintr++;
    163  1.1.2.2  jdc 
    164  1.1.2.2  jdc 	bcm2835_barrier();
    165  1.1.2.2  jdc 	ipl_mask = bcm2835_pic_find_pending_irqs(&bcm2835_pic);
    166  1.1.2.2  jdc 
    167  1.1.2.2  jdc 	/*
    168  1.1.2.2  jdc 	 * Record the pending_ipls and deliver them if we can.
    169  1.1.2.2  jdc 	 */
    170  1.1.2.2  jdc 	if ((ipl_mask & ~oldipl_mask) > oldipl_mask)
    171  1.1.2.2  jdc 		pic_do_pending_ints(I32_bit, oldipl, frame);
    172  1.1.2.2  jdc }
    173  1.1.2.2  jdc 
    174  1.1.2.2  jdc 
    175  1.1.2.2  jdc static void
    176  1.1.2.2  jdc bcm2835_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
    177  1.1.2.2  jdc     uint32_t irq_mask)
    178  1.1.2.2  jdc {
    179  1.1.2.2  jdc 
    180  1.1.2.2  jdc 	write_bcm2835reg(BCM2835_INTC_ENABLEBASE + (irqbase >> 3), irq_mask);
    181  1.1.2.2  jdc 	bcm2835_barrier();
    182  1.1.2.2  jdc }
    183  1.1.2.2  jdc 
    184  1.1.2.2  jdc static void
    185  1.1.2.2  jdc bcm2835_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
    186  1.1.2.2  jdc     uint32_t irq_mask)
    187  1.1.2.2  jdc {
    188  1.1.2.2  jdc 
    189  1.1.2.2  jdc 	write_bcm2835reg(BCM2835_INTC_DISABLEBASE + (irqbase >> 3), irq_mask);
    190  1.1.2.2  jdc 	bcm2835_barrier();
    191  1.1.2.2  jdc }
    192  1.1.2.2  jdc 
    193  1.1.2.2  jdc /*
    194  1.1.2.2  jdc  * Called with interrupts disabled
    195  1.1.2.2  jdc  */
    196  1.1.2.2  jdc static int
    197  1.1.2.2  jdc bcm2835_pic_find_pending_irqs(struct pic_softc *pic)
    198  1.1.2.2  jdc {
    199  1.1.2.2  jdc 	int ipl = 0;
    200  1.1.2.2  jdc 	uint32_t bpending, gpu0irq, gpu1irq, armirq;
    201  1.1.2.2  jdc 
    202  1.1.2.2  jdc 	bcm2835_barrier();
    203  1.1.2.2  jdc 	bpending = read_bcm2835reg(BCM2835_INTC_IRQBPENDING);
    204  1.1.2.2  jdc 	if (bpending == 0)
    205  1.1.2.2  jdc 		return 0;
    206  1.1.2.2  jdc 
    207  1.1.2.2  jdc 	armirq = bpending & BCM2835_INTBIT_ARM;
    208  1.1.2.2  jdc 	gpu0irq = bpending & BCM2835_INTBIT_GPU0;
    209  1.1.2.2  jdc 	gpu1irq = bpending & BCM2835_INTBIT_GPU1;
    210  1.1.2.2  jdc 
    211  1.1.2.2  jdc 	if (armirq) {
    212  1.1.2.2  jdc 		ipl |= pic_mark_pending_sources(pic, BCM2835_INT_BASICBASE,
    213  1.1.2.2  jdc 		    armirq);
    214  1.1.2.4  riz 
    215  1.1.2.2  jdc 	}
    216  1.1.2.2  jdc 
    217  1.1.2.2  jdc 	if (gpu0irq || (bpending & BCM2835_INTBIT_PENDING1)) {
    218  1.1.2.2  jdc 		uint32_t pending1;
    219  1.1.2.4  riz 
    220  1.1.2.2  jdc 		pending1 = read_bcm2835reg(BCM2835_INTC_IRQ1PENDING);
    221  1.1.2.2  jdc 		ipl |= pic_mark_pending_sources(pic, BCM2835_INT_GPU0BASE,
    222  1.1.2.2  jdc 		    pending1);
    223  1.1.2.2  jdc 	}
    224  1.1.2.2  jdc 	if (gpu1irq || (bpending & BCM2835_INTBIT_PENDING2)) {
    225  1.1.2.2  jdc 		uint32_t pending2;
    226  1.1.2.4  riz 
    227  1.1.2.2  jdc 		pending2 = read_bcm2835reg(BCM2835_INTC_IRQ2PENDING);
    228  1.1.2.2  jdc 		ipl |= pic_mark_pending_sources(pic, BCM2835_INT_GPU1BASE,
    229  1.1.2.2  jdc 		    pending2);
    230  1.1.2.2  jdc 	}
    231  1.1.2.4  riz 
    232  1.1.2.2  jdc 	return ipl;
    233  1.1.2.2  jdc }
    234  1.1.2.2  jdc 
    235  1.1.2.2  jdc static void
    236  1.1.2.2  jdc bcm2835_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
    237  1.1.2.2  jdc {
    238  1.1.2.2  jdc 
    239  1.1.2.2  jdc 	/* Nothing really*/
    240  1.1.2.2  jdc 	KASSERT(is->is_irq < BCM2835_NIRQ);
    241  1.1.2.2  jdc 	KASSERT(is->is_type == IST_LEVEL);
    242  1.1.2.2  jdc }
    243  1.1.2.2  jdc 
    244  1.1.2.2  jdc static void
    245  1.1.2.2  jdc bcm2835_pic_source_name(struct pic_softc *pic, int irq, char *buf, size_t len)
    246  1.1.2.2  jdc {
    247  1.1.2.2  jdc 
    248  1.1.2.2  jdc 	strlcpy(buf, bcm2835_sources[irq], len);
    249  1.1.2.2  jdc }
    250