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