Home | History | Annotate | Line # | Download | only in marvell
pic_discovery.c revision 1.2
      1  1.2  garbled /*	$NetBSD: pic_discovery.c,v 1.2 2007/10/17 19:56:42 garbled Exp $	*/
      2  1.2  garbled 
      3  1.2  garbled /*
      4  1.2  garbled  * Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc.
      5  1.2  garbled  * All rights reserved.
      6  1.2  garbled  *
      7  1.2  garbled  * Redistribution and use in source and binary forms, with or without
      8  1.2  garbled  * modification, are permitted provided that the following conditions
      9  1.2  garbled  * are met:
     10  1.2  garbled  * 1. Redistributions of source code must retain the above copyright
     11  1.2  garbled  *    notice, this list of conditions and the following disclaimer.
     12  1.2  garbled  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.2  garbled  *    notice, this list of conditions and the following disclaimer in the
     14  1.2  garbled  *    documentation and/or other materials provided with the distribution.
     15  1.2  garbled  * 3. All advertising materials mentioning features or use of this software
     16  1.2  garbled  *    must display the following acknowledgement:
     17  1.2  garbled  *      This product includes software developed for the NetBSD Project by
     18  1.2  garbled  *      Allegro Networks, Inc., and Wasabi Systems, Inc.
     19  1.2  garbled  * 4. The name of Allegro Networks, Inc. may not be used to endorse
     20  1.2  garbled  *    or promote products derived from this software without specific prior
     21  1.2  garbled  *    written permission.
     22  1.2  garbled  * 5. The name of Wasabi Systems, Inc. may not be used to endorse
     23  1.2  garbled  *    or promote products derived from this software without specific prior
     24  1.2  garbled  *    written permission.
     25  1.2  garbled  *
     26  1.2  garbled  * THIS SOFTWARE IS PROVIDED BY ALLEGRO NETWORKS, INC. AND
     27  1.2  garbled  * WASABI SYSTEMS, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     28  1.2  garbled  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
     29  1.2  garbled  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     30  1.2  garbled  * IN NO EVENT SHALL EITHER ALLEGRO NETWORKS, INC. OR WASABI SYSTEMS, INC.
     31  1.2  garbled  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  1.2  garbled  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  1.2  garbled  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  1.2  garbled  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  1.2  garbled  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  1.2  garbled  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  1.2  garbled  * POSSIBILITY OF SUCH DAMAGE.
     38  1.2  garbled  */
     39  1.2  garbled 
     40  1.2  garbled /*
     41  1.2  garbled  * extintr.c - external interrupt management for discovery
     42  1.2  garbled  *
     43  1.2  garbled  *	Interrupts are software-prioritized and preempting,
     44  1.2  garbled  *	they are only actually masked when pending.
     45  1.2  garbled  *	this allows avoiding slow, off-CPU mask reprogramming for spl/splx.
     46  1.2  garbled  *	When a lower priority interrupt preempts a high one,
     47  1.2  garbled  *	it is pended and masked.  Masks are re-enabled after service.
     48  1.2  garbled  *
     49  1.2  garbled  *	`ci->ci_cpl'   is a "priority level" not a bitmask.
     50  1.2  garbled  *	`irq'   is a bit number in the 128 bit imask_t which reflects
     51  1.2  garbled  *		the GT-64260 Main Cause register pair (64 bits), and
     52  1.2  garbled  *		GPP Cause register (32 bits) interrupts.
     53  1.2  garbled  *
     54  1.2  garbled  *	Intra IPL dispatch order is defined in cause_irq()
     55  1.2  garbled  *
     56  1.2  garbled  *	Summary bits in cause registers are not valid IRQs
     57  1.2  garbled  *
     58  1.2  garbled  * 	Within a cause register bit vector ISRs are called in
     59  1.2  garbled  *	order of IRQ (descending).
     60  1.2  garbled  *
     61  1.2  garbled  *	When IRQs are shared, ISRs are called in order on the queue
     62  1.2  garbled  *	(which is arbitrarily first-established-first-served).
     63  1.2  garbled  *
     64  1.2  garbled  *	GT64260 GPP setup is for edge-triggered interrupts.
     65  1.2  garbled  *	We maintain a mask of level-triggered type IRQs
     66  1.2  garbled  *	and gather unlatched level from the GPP Value register.
     67  1.2  garbled  *
     68  1.2  garbled  *	Software interrupts are just like regular IRQs,
     69  1.2  garbled  *	they are established, pended, and dispatched exactly the
     70  1.2  garbled  *	same as HW interrupts.
     71  1.2  garbled  *
     72  1.2  garbled  *	128 bit imask_t operations could be implemented with Altivec
     73  1.2  garbled  *	("vand", "vor", etc however no "vcntlzw" or "vffs"....)
     74  1.2  garbled  *
     75  1.2  garbled  * creation	Tue Feb  6 17:27:18 PST 2001	cliff
     76  1.2  garbled  */
     77  1.2  garbled 
     78  1.2  garbled #include <sys/cdefs.h>
     79  1.2  garbled __KERNEL_RCSID(0, "$NetBSD: pic_discovery.c,v 1.2 2007/10/17 19:56:42 garbled Exp $");
     80  1.2  garbled 
     81  1.2  garbled #include "opt_marvell.h"
     82  1.2  garbled #include "opt_kgdb.h"
     83  1.2  garbled 
     84  1.2  garbled #include <sys/param.h>
     85  1.2  garbled #include <sys/systm.h>
     86  1.2  garbled #include <sys/types.h>
     87  1.2  garbled #include <sys/malloc.h>
     88  1.2  garbled #include <sys/kernel.h>
     89  1.2  garbled 
     90  1.2  garbled #include <machine/psl.h>
     91  1.2  garbled #include <machine/bus.h>
     92  1.2  garbled #include <machine/cpu.h>
     93  1.2  garbled #include <machine/intr.h>
     94  1.2  garbled #include <powerpc/pic/picvar.h>
     95  1.2  garbled #ifdef KGDB
     96  1.2  garbled #include <machine/db_machdep.h>
     97  1.2  garbled #endif
     98  1.2  garbled #include <dev/marvell/gtreg.h>
     99  1.2  garbled #include <dev/marvell/gtvar.h>
    100  1.2  garbled #include <dev/marvell/gtintrreg.h>
    101  1.2  garbled 
    102  1.2  garbled #include <uvm/uvm_extern.h>
    103  1.2  garbled 
    104  1.2  garbled #if defined(DEBUG) && defined(DDB)
    105  1.2  garbled #endif
    106  1.2  garbled 
    107  1.2  garbled #ifdef DEBUG
    108  1.2  garbled # define STATIC
    109  1.2  garbled int intrdebug = 0;
    110  1.2  garbled # define DPRINTF(x)		do { if (intrdebug) printf x ; } while (0)
    111  1.2  garbled # define DPRINTFN(n, x)		do { if (intrdebug > (n)) printf x ; } while (0)
    112  1.2  garbled #else
    113  1.2  garbled # define STATIC static
    114  1.2  garbled # define DPRINTF(x)
    115  1.2  garbled # define DPRINTFN(n, x)
    116  1.2  garbled #endif
    117  1.2  garbled 
    118  1.2  garbled #ifdef DIAGNOSTIC
    119  1.2  garbled # define DIAGPRF(x)		printf x
    120  1.2  garbled #else
    121  1.2  garbled # define DIAGPRF(x)
    122  1.2  garbled #endif
    123  1.2  garbled 
    124  1.2  garbled #define ILLEGAL_IRQ(x) (((x) < 0) || ((x) >= NIRQ) || \
    125  1.2  garbled 		 ((1<<((x)&IMASK_BITMASK)) & imres.bits[(x)>>IMASK_WORDSHIFT]))
    126  1.2  garbled 
    127  1.2  garbled extern struct powerpc_bus_space gt_mem_bs_tag;
    128  1.2  garbled extern bus_space_handle_t gt_memh;
    129  1.2  garbled 
    130  1.2  garbled static const char intr_source_strings[NIRQ][16] = {
    131  1.2  garbled 	"unknown 0",	"dev",		"dma",		"cpu",
    132  1.2  garbled 	"idma 01",	"idma 23",	"idma 45",	"idma 67",
    133  1.2  garbled 	"timer 01",	"timer 23",	"timer 45",	"timer 67",
    134  1.2  garbled 	"pci0-0",	"pci0-1",	"pci0-2",	"pci0-3",
    135  1.2  garbled /*16*/	"pci1-0",	"ecc",		"pci1-1",	"pci1-2",
    136  1.2  garbled 	"pci1-3",	"pci0-outl",	"pci0-outh",	"pci1-outl",
    137  1.2  garbled 	"pci1-outh",	"unknown 25",	"pci0-inl",	"pci0-inh",
    138  1.2  garbled 	"pci1-inl",	"pci1-inh",	"unknown 30",	"unknown 31",
    139  1.2  garbled /*32*/	"ether 0",	"ether 1",	"ether 2",	"unknown 35",
    140  1.2  garbled 	"sdma",		"iic",		"unknown 38",	"brg",
    141  1.2  garbled 	"mpsc 0",	"unknown 41",	"mpsc 1",	"comm",
    142  1.2  garbled 	"unknown 44",	"unknown 45",	"unknown 46",	"unknown 47",
    143  1.2  garbled /*48*/	"unknown 48",	"unknown 49",	"unknown 50",	"unknown 51",
    144  1.2  garbled 	"unknown 52",	"unknown 53",	"unknown 54",	"unknown 55",
    145  1.2  garbled 	"gppsum 0",	"gppsum 1",	"gppsum 2",	"gppsum 3",
    146  1.2  garbled 	"unknown 60",	"unknown 61",	"unknown 62",	"unknown 63",
    147  1.2  garbled };
    148  1.2  garbled 
    149  1.2  garbled struct discovery_pic_ops {
    150  1.2  garbled 	struct pic_ops dsc_pic;
    151  1.2  garbled 	bus_space_tag_t dsc_memt;
    152  1.2  garbled 	bus_space_tag_t dsc_memh;
    153  1.2  garbled 	uint32_t dsc_interrupt_mask[2];
    154  1.2  garbled 	uint8_t dsc_priority[64];
    155  1.2  garbled 	uint8_t dsc_maxpriority[64];
    156  1.2  garbled };
    157  1.2  garbled 
    158  1.2  garbled struct gpp_pic_ops {
    159  1.2  garbled 	struct pic_ops gpp_pic;
    160  1.2  garbled 	bus_space_tag_t gpp_memt;
    161  1.2  garbled 	bus_space_handle_t gpp_memh;
    162  1.2  garbled 	uint32_t gpp_interrupt_mask;
    163  1.2  garbled 	uint8_t gpp_priority[32];
    164  1.2  garbled 	uint8_t gpp_maxpriority[32];
    165  1.2  garbled };
    166  1.2  garbled 
    167  1.2  garbled static void
    168  1.2  garbled gpp_source_name(struct pic_ops *pic, int irq, char *name, size_t len)
    169  1.2  garbled {
    170  1.2  garbled 	snprintf(name, len, "gpp %d", irq);
    171  1.2  garbled }
    172  1.2  garbled 
    173  1.2  garbled #define GPP_RES ~GT_MPP_INTERRUPTS	/* from config */
    174  1.2  garbled 
    175  1.2  garbled static int
    176  1.2  garbled gpp_get_irq(struct pic_ops *pic)
    177  1.2  garbled {
    178  1.2  garbled 	struct gpppic_ops * const gpp = (void *)pic;
    179  1.2  garbled 	uint32_t mask;
    180  1.2  garbled 	int maybe_irq = -1;
    181  1.2  garbled 	int maybe_priority = IPL_NONE;
    182  1.2  garbled 
    183  1.2  garbled #ifdef GPP_EDGE
    184  1.2  garbled 	mask = bus_space_read_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Interrupt_Cause);
    185  1.2  garbled #else
    186  1.2  garbled 	mask = bus_space_read_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Value);
    187  1.2  garbled #endif
    188  1.2  garbled 	mask &= gpp->gpp_interrupt_mask;
    189  1.2  garbled 	if (mask == 0)
    190  1.2  garbled 		return NO_IRQ;
    191  1.2  garbled 
    192  1.2  garbled 	while (mask != 0) {
    193  1.2  garbled 		int irq = 32 - __builtin_clz(mask);
    194  1.2  garbled 		if (gpp->gpp_priority[irq] > maybe_irq) {
    195  1.2  garbled 			maybe_irq = irq;
    196  1.2  garbled 			maybe_priority = gpp->gpp_priority[irq];
    197  1.2  garbled 			if (maybe_priority > gpp->gpp_maxpriority[irq])
    198  1.2  garbled 				break;
    199  1.2  garbled 		}
    200  1.2  garbled 		mask &= ~(1 << irq);
    201  1.2  garbled 	}
    202  1.2  garbled 	/*
    203  1.2  garbled 	 * We now have the highest priority IRQ.
    204  1.2  garbled 	 */
    205  1.2  garbled 	KASSERT(maybe_irq >= 0);
    206  1.2  garbled #ifdef GPP_EDGE
    207  1.2  garbled 	mask = 1 << maybe_irq;
    208  1.2  garbled 	bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Interrupt_Cause, mask);
    209  1.2  garbled #endif
    210  1.2  garbled 
    211  1.2  garbled 	return maybe_irq;
    212  1.2  garbled }
    213  1.2  garbled 
    214  1.2  garbled static void
    215  1.2  garbled gpp_establish_irq(struct pic_ops *pic, int irq, int type, int pri)
    216  1.2  garbled {
    217  1.2  garbled 	struct gpppic_ops * const gpp = (void *)pic;
    218  1.2  garbled 	const uint32_t mask = 1 << irq;
    219  1.2  garbled 
    220  1.2  garbled 	KASSERT((unsigned) irq < 32);
    221  1.2  garbled #ifdef GPP_EDGE
    222  1.2  garbled 	KASSERT(type == IST_EDGE);
    223  1.2  garbled #else
    224  1.2  garbled 	KASSERT(type == IST_LEVEL);
    225  1.2  garbled #endif
    226  1.2  garbled 
    227  1.2  garbled 	/*
    228  1.2  garbled 	 * Set pin to input and active low.
    229  1.2  garbled 	 */
    230  1.2  garbled 	val = bus_space_read_4(gpp->gpp_memt, gpp->gpp_memh, GT_GPP_IO_Control);
    231  1.2  garbled 	val &= ~mask;
    232  1.2  garbled 	bus_space_write_4(gpp->gpp_memt, gpp->gpp_memh, GT_GPP_IO_Control, val);
    233  1.2  garbled 
    234  1.2  garbled 	val = bus_space_read_4(gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Level_Control);
    235  1.2  garbled 	val |= mask;
    236  1.2  garbled 	bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Level_Control, val);
    237  1.2  garbled 
    238  1.2  garbled 	gpp->gpp_priority[irq] = pri;
    239  1.2  garbled 
    240  1.2  garbled 	/*
    241  1.2  garbled 	 * recalculate the maxpriority of an interrupt.  This is highest
    242  1.2  garbled 	 * priority interrupt from itself to gpp0.
    243  1.2  garbled 	 */
    244  1.2  garbled 	pri = IPL_NONE;
    245  1.2  garbled 	for (i = 0; i < __arraycount(gpp->gpp_priority); i++) {
    246  1.2  garbled 		if (gpp->gpp_priority[i] > pri)
    247  1.2  garbled 			pri = gpp->gpp_priority[i];
    248  1.2  garbled 		gpp->gpp_maxpriority[i] = pri;
    249  1.2  garbled 	}
    250  1.2  garbled }
    251  1.2  garbled 
    252  1.2  garbled static void
    253  1.2  garbled gpp_enable_irq(struct pic_ops *pic, int irq, int type)
    254  1.2  garbled {
    255  1.2  garbled 	struct gpppic_ops * const gpp = (void *)pic;
    256  1.2  garbled 	const uint32_t mask = 1 << irq;
    257  1.2  garbled 
    258  1.2  garbled 	KASSERT(type == IST_LEVEL);
    259  1.2  garbled 	KASSERT(gpp->gpp_priority[irq] != IPL_NONE);
    260  1.2  garbled 	gpp->gpp_interrupt_mask |= mask;
    261  1.2  garbled 	bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Interrupt_Mask,
    262  1.2  garbled 	    gpp->gpp_interrupt_mask);
    263  1.2  garbled }
    264  1.2  garbled 
    265  1.2  garbled static void
    266  1.2  garbled gpp_disable_irq(struct pic_ops *pic, int irq)
    267  1.2  garbled {
    268  1.2  garbled 	struct gpppic_ops * const gpp = (void *)pic;
    269  1.2  garbled 	const uint32_t mask = 1 << irq;
    270  1.2  garbled 
    271  1.2  garbled 	gpp->gpp_interrupt_mask &= ~mask;
    272  1.2  garbled 	bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Interrupt_Mask,
    273  1.2  garbled 	    gpp->gpp_interrupt_mask);
    274  1.2  garbled }
    275  1.2  garbled 
    276  1.2  garbled static void
    277  1.2  garbled gpp_ack_irq(struct pic_ops *pic, int irq)
    278  1.2  garbled {
    279  1.2  garbled }
    280  1.2  garbled 
    281  1.2  garbled static struct pic_ops *
    282  1.2  garbled gpp_pic_setup(bus_space_tag_t memt, bus_space_handle_t memh)
    283  1.2  garbled {
    284  1.2  garbled 	struct gpppic_ops * gpp;
    285  1.2  garbled 	uint32_t val;
    286  1.2  garbled 
    287  1.2  garbled 	gpp = malloc(sizeof(*gpp), M_DEVBUF, M_NOWAIT|M_ZERO);
    288  1.2  garbled 	if (!gpp)
    289  1.2  garbled 		panic("gpp_pic_setup: malloc(%zu) failed", sizeof(*gpp));
    290  1.2  garbled 
    291  1.2  garbled 	gpp->gpp_memt = memt;
    292  1.2  garbled 	gpp->gpp_memh = memh;
    293  1.2  garbled 	gpp->gpp_pic.pic_get_irq = gpp_get_irq;
    294  1.2  garbled 	gpp->gpp_pic.pic_enable_irq = gpp_enable_irq;
    295  1.2  garbled 	gpp->gpp_pic.pic_reenable_irq = gpp_enable_irq;
    296  1.2  garbled 	gpp->gpp_pic.pic_disable_irq = gpp_disable_irq;
    297  1.2  garbled 	gpp->gpp_pic.pic_ack_irq = gpp_ack_irq;
    298  1.2  garbled 	gpp->gpp_pic.pic_establish_irq = gpp_establish_irq;
    299  1.2  garbled 	gpp->gpp_pic.pic_source_name = gpp_source_name;
    300  1.2  garbled 
    301  1.2  garbled 	/*
    302  1.2  garbled 	 * Force GPP interrupts to be level sensitive.
    303  1.2  garbled 	 */
    304  1.2  garbled 	val = bus_space_read_4(&gpp->gpp_memt, gpp->gpp_memh, 0xf300);
    305  1.2  garbled 	bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, 0xf300, val | 0x400);
    306  1.2  garbled 
    307  1.2  garbled 	pic_add(&gpp->gpp_pic);
    308  1.2  garbled 
    309  1.2  garbled 	return &gpp->gpp_pic;
    310  1.2  garbled }
    311  1.2  garbled 
    312  1.2  garbled static void
    313  1.2  garbled discovery_source_name(struct pic_ops *pic, int irq, char *name, size_t len)
    314  1.2  garbled {
    315  1.2  garbled 	strlcpy(name, discovery_intr_source_strings[irq], len);
    316  1.2  garbled }
    317  1.2  garbled 
    318  1.2  garbled static int
    319  1.2  garbled discovery_get_irq(struct pic_ops *pic)
    320  1.2  garbled {
    321  1.2  garbled 	struct discoverypic_ops * const dsc = (void *)pic;
    322  1.2  garbled 	uint32_t mask;
    323  1.2  garbled 	int irq_base = 0;
    324  1.2  garbled 	int maybe_irq = -1;
    325  1.2  garbled 	int maybe_priority = IPL_NONE;
    326  1.2  garbled 
    327  1.2  garbled 	mask = bus_space_read_4(&dsc->dsc_memt, dsc->dsc_memh, ICR_CSC);
    328  1.2  garbled 	if (!(mask & CSC_STAT))
    329  1.2  garbled 		return NO_IRQ;
    330  1.2  garbled 	irq_base = (mask & CSC_SEL) ? 32 : 0;
    331  1.2  garbled 	mask &= dsc->dsc_interrupt_mask[(mask & CSC_SEL) ? 1 : 0];
    332  1.2  garbled 	while (mask != 0) {
    333  1.2  garbled 		int irq = 32 - __builtin_clz(mask);
    334  1.2  garbled 		if (dsc->dsc_priority[irq_base + irq] > maybe_irq) {
    335  1.2  garbled 			maybe_irq = irq_base + irq;
    336  1.2  garbled 			maybe_priority = dsc->dsc_priority[irq_base + irq];
    337  1.2  garbled 			if (maybe_priority > dsc->dsc_maxpriority[irq_base + irq])
    338  1.2  garbled 				break;
    339  1.2  garbled 		}
    340  1.2  garbled 		mask &= ~(1 << irq);
    341  1.2  garbled 	}
    342  1.2  garbled 	/*
    343  1.2  garbled 	 * We now have the highest priority IRQ (except it's cascaded).
    344  1.2  garbled 	 */
    345  1.2  garbled 	KASSERT(maybe_irq >= 0);
    346  1.2  garbled 	return maybe_irq;
    347  1.2  garbled }
    348  1.2  garbled 
    349  1.2  garbled static void
    350  1.2  garbled discovery_establish_irq(struct pic_ops *pic, int irq, int type, int pri)
    351  1.2  garbled {
    352  1.2  garbled 	struct discoverypic_ops * const dsc = (void *)pic;
    353  1.2  garbled 
    354  1.2  garbled 	KASSERT((unsigned) irq < 32);
    355  1.2  garbled #ifdef GPP_EDGE
    356  1.2  garbled 	KASSERT(type == IST_EDGE);
    357  1.2  garbled #else
    358  1.2  garbled 	KASSERT(type == IST_LEVEL);
    359  1.2  garbled #endif
    360  1.2  garbled 
    361  1.2  garbled 	dsc->dsc_priority[irq] = pri;
    362  1.2  garbled 
    363  1.2  garbled 	/*
    364  1.2  garbled 	 * recalculate the maxpriority of an interrupt.  This is highest
    365  1.2  garbled 	 * priority interrupt from itself to irq 0.
    366  1.2  garbled 	 */
    367  1.2  garbled 	pri = IPL_NONE;
    368  1.2  garbled 	for (i = 0; i < __arraycount(dsc->dsc_priority); i++) {
    369  1.2  garbled 		if (dsc->dsc_priority[i] > pri)
    370  1.2  garbled 			pri = dsc->dsc_priority[i];
    371  1.2  garbled 		dsc->dsc_maxpriority[i] = pri;
    372  1.2  garbled 	}
    373  1.2  garbled }
    374  1.2  garbled 
    375  1.2  garbled static void
    376  1.2  garbled discovery_enable_irq(struct pic_ops *pic, int irq, int type)
    377  1.2  garbled {
    378  1.2  garbled 	struct discoverypic_ops * const dsc = (void *)pic;
    379  1.2  garbled 	const uint32_t mask = 1 << (irq & 31);
    380  1.2  garbled 
    381  1.2  garbled 	KASSERT(type == IST_LEVEL);
    382  1.2  garbled 	KASSERT(dsc->dsc_priority[irq] != IPL_NONE);
    383  1.2  garbled 	if (irq < 32) {
    384  1.2  garbled 		dsc->dsc_interrupt_mask[0] |= mask;
    385  1.2  garbled 		bus_space_write_4(&dsc->dsc_memt, dsc->dsc_memh,
    386  1.2  garbled 		    ICR_MIC_LO, dsc->dsc_interrupt_mask[0]);
    387  1.2  garbled 	} else {
    388  1.2  garbled 		dsc->dsc_interrupt_mask[1] |= mask;
    389  1.2  garbled 		bus_space_write_4(&dsc->dsc_memt, dsc->dsc_memh,
    390  1.2  garbled 		    ICR_MIC_HI, dsc->dsc_interrupt_mask[1]);
    391  1.2  garbled 	}
    392  1.2  garbled }
    393  1.2  garbled 
    394  1.2  garbled static void
    395  1.2  garbled discovery_disable_irq(struct pic_ops *pic, int irq)
    396  1.2  garbled {
    397  1.2  garbled 	struct discoverypic_ops * const dsc = (void *)pic;
    398  1.2  garbled 	const uint32_t mask = 1 << (irq & 31);
    399  1.2  garbled 
    400  1.2  garbled 	if (irq < 32) {
    401  1.2  garbled 		dsc->dsc_interrupt_mask[0] &= ~mask;
    402  1.2  garbled 		bus_space_write_4(&dsc->dsc_memt, dsc->dsc_memh,
    403  1.2  garbled 		    ICR_MIC_LO, dsc->dsc_interrupt_mask[0]);
    404  1.2  garbled 	} else {
    405  1.2  garbled 		dsc->dsc_interrupt_mask[1] &= ~mask;
    406  1.2  garbled 		bus_space_write_4(&dsc->dsc_memt, dsc->dsc_memh,
    407  1.2  garbled 		    ICR_MIC_HI, dsc->dsc_interrupt_mask[1]);
    408  1.2  garbled 	}
    409  1.2  garbled }
    410  1.2  garbled 
    411  1.2  garbled static void
    412  1.2  garbled discovery_ack_irq(struct pic_ops *pic, int irq)
    413  1.2  garbled {
    414  1.2  garbled }
    415  1.2  garbled 
    416  1.2  garbled void
    417  1.2  garbled discoverypic_setup(bus_space_tag_t memt, bus_space_handle_t memh)
    418  1.2  garbled {
    419  1.2  garbled 	struct discoverypic_ops *dsc;
    420  1.2  garbled 	uint32_t val;
    421  1.2  garbled 
    422  1.2  garbled 	dsc = malloc(sizeof(*dsc), M_DEVBUF, M_NOWAIT|M_ZERO);
    423  1.2  garbled 	if (!dsc)
    424  1.2  garbled 		panic("dsc_pic_setup: malloc(%zu) failed", sizeof(*dsc));
    425  1.2  garbled 
    426  1.2  garbled 	dsc->dsc_memt = memt;
    427  1.2  garbled 	dsc->dsc_memh = memh;
    428  1.2  garbled 	dsc->dsc_pic.pic_get_irq = dsc_get_irq;
    429  1.2  garbled 	dsc->dsc_pic.pic_enable_irq = dsc_enable_irq;
    430  1.2  garbled 	dsc->dsc_pic.pic_reenable_irq = dsc_enable_irq;
    431  1.2  garbled 	dsc->dsc_pic.pic_disable_irq = dsc_disable_irq;
    432  1.2  garbled 	dsc->dsc_pic.pic_ack_irq = dsc_ack_irq;
    433  1.2  garbled 	dsc->dsc_pic.pic_establish_irq = dsc_establish_irq;
    434  1.2  garbled 	dsc->dsc_pic.pic_source_name = dsc_source_name;
    435  1.2  garbled 
    436  1.2  garbled 	pic_add(&dsc->dsc_pic);
    437  1.2  garbled 	KASSERT(dsc->dsc_pic.pic_intrbase == 0);
    438  1.2  garbled 
    439  1.2  garbled 	pic = dscpic_setup(memt, memh);
    440  1.2  garbled 	intr_establish(dsc->dsc_pic.pic_intrbase + IRQ_GPP7_0,
    441  1.2  garbled 	    IST_LEVEL, IPL_NONE, pic_handle_intr, pic);
    442  1.2  garbled 	intr_establish(dsc->dsc_pic.pic_intrbase + IRQ_GPP15_8,
    443  1.2  garbled 	    IST_LEVEL, IPL_NONE, pic_handle_intr, pic);
    444  1.2  garbled 	intr_establish(dsc->dsc_pic.pic_intrbase + IRQ_GPP23_16,
    445  1.2  garbled 	    IST_LEVEL, IPL_NONE, pic_handle_intr, pic);
    446  1.2  garbled 	intr_establish(dsc->dsc_pic.pic_intrbase + IRQ_GPP31_24,
    447  1.2  garbled 	    IST_LEVEL, IPL_NONE, pic_handle_intr, pic);
    448  1.2  garbled }
    449