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