Home | History | Annotate | Line # | Download | only in rmi
rmixl_intr.c revision 1.2
      1  1.2  matt /*	$NetBSD: rmixl_intr.c,v 1.2 2009/12/14 00:46:07 matt Exp $	*/
      2  1.2  matt 
      3  1.2  matt /*-
      4  1.2  matt  * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko.
      5  1.2  matt  * All rights reserved.
      6  1.2  matt  *
      7  1.2  matt  * Redistribution and use in source and binary forms, with or
      8  1.2  matt  * without modification, are permitted provided that the following
      9  1.2  matt  * conditions are met:
     10  1.2  matt  * 1. Redistributions of source code must retain the above copyright
     11  1.2  matt  *    notice, this list of conditions and the following disclaimer.
     12  1.2  matt  * 2. Redistributions in binary form must reproduce the above
     13  1.2  matt  *    copyright notice, this list of conditions and the following
     14  1.2  matt  *    disclaimer in the documentation and/or other materials provided
     15  1.2  matt  *    with the distribution.
     16  1.2  matt  * 3. The names of the authors may not be used to endorse or promote
     17  1.2  matt  *    products derived from this software without specific prior
     18  1.2  matt  *    written permission.
     19  1.2  matt  *
     20  1.2  matt  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY
     21  1.2  matt  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     22  1.2  matt  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     23  1.2  matt  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS
     24  1.2  matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
     25  1.2  matt  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  1.2  matt  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
     27  1.2  matt  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  1.2  matt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
     29  1.2  matt  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     30  1.2  matt  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
     31  1.2  matt  * OF SUCH DAMAGE.
     32  1.2  matt  */
     33  1.2  matt /*-
     34  1.2  matt  * Copyright (c) 2001 The NetBSD Foundation, Inc.
     35  1.2  matt  * All rights reserved.
     36  1.2  matt  *
     37  1.2  matt  * This code is derived from software contributed to The NetBSD Foundation
     38  1.2  matt  * by Jason R. Thorpe.
     39  1.2  matt  *
     40  1.2  matt  * Redistribution and use in source and binary forms, with or without
     41  1.2  matt  * modification, are permitted provided that the following conditions
     42  1.2  matt  * are met:
     43  1.2  matt  * 1. Redistributions of source code must retain the above copyright
     44  1.2  matt  *    notice, this list of conditions and the following disclaimer.
     45  1.2  matt  * 2. Redistributions in binary form must reproduce the above copyright
     46  1.2  matt  *    notice, this list of conditions and the following disclaimer in the
     47  1.2  matt  *    documentation and/or other materials provided with the distribution.
     48  1.2  matt  *
     49  1.2  matt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     50  1.2  matt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     51  1.2  matt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     52  1.2  matt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     53  1.2  matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     54  1.2  matt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     55  1.2  matt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     56  1.2  matt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     57  1.2  matt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     58  1.2  matt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     59  1.2  matt  * POSSIBILITY OF SUCH DAMAGE.
     60  1.2  matt  */
     61  1.2  matt 
     62  1.2  matt /*
     63  1.2  matt  * Platform-specific interrupt support for the RMI XLP, XLR, XLS
     64  1.2  matt  */
     65  1.2  matt 
     66  1.2  matt #include <sys/cdefs.h>
     67  1.2  matt __KERNEL_RCSID(0, "$NetBSD: rmixl_intr.c,v 1.2 2009/12/14 00:46:07 matt Exp $");
     68  1.2  matt 
     69  1.2  matt #include "opt_ddb.h"
     70  1.2  matt 
     71  1.2  matt #include <sys/param.h>
     72  1.2  matt #include <sys/queue.h>
     73  1.2  matt #include <sys/malloc.h>
     74  1.2  matt #include <sys/systm.h>
     75  1.2  matt #include <sys/device.h>
     76  1.2  matt #include <sys/kernel.h>
     77  1.2  matt 
     78  1.2  matt #include <machine/bus.h>
     79  1.2  matt #include <machine/intr.h>
     80  1.2  matt 
     81  1.2  matt #include <mips/cpu.h>
     82  1.2  matt #include <mips/locore.h>
     83  1.2  matt 
     84  1.2  matt #include <mips/rmi/rmixlreg.h>
     85  1.2  matt #include <mips/rmi/rmixlvar.h>
     86  1.2  matt 
     87  1.2  matt #include <dev/pci/pcireg.h>
     88  1.2  matt #include <dev/pci/pcivar.h>
     89  1.2  matt 
     90  1.2  matt #ifdef IOINTR_DEBUG
     91  1.2  matt int iointr_debug = IOINTR_DEBUG;
     92  1.2  matt # define DPRINTF(x)	do { if (iointr_debug) printf x ; } while(0)
     93  1.2  matt #else
     94  1.2  matt # define DPRINTF(x)
     95  1.2  matt #endif
     96  1.2  matt 
     97  1.2  matt #define RMIXL_PICREG_READ(off) \
     98  1.2  matt 	RMIXL_IOREG_READ(RMIXL_IO_DEV_PIC + (off))
     99  1.2  matt #define RMIXL_PICREG_WRITE(off, val) \
    100  1.2  matt 	RMIXL_IOREG_WRITE(RMIXL_IO_DEV_PIC + (off), (val))
    101  1.2  matt /*
    102  1.2  matt  * This is a mask of bits to clear in the SR when we go to a
    103  1.2  matt  * given hardware interrupt priority level.
    104  1.2  matt  * _SR_BITS_DFLT bits are to be always clear (disabled)
    105  1.2  matt  */
    106  1.2  matt #define _SR_BITS_DFLT	(MIPS_INT_MASK_2|MIPS_INT_MASK_3|MIPS_INT_MASK_4)
    107  1.2  matt const uint32_t ipl_sr_bits[_IPL_N] = {
    108  1.2  matt 	[IPL_NONE] = _SR_BITS_DFLT,
    109  1.2  matt 	[IPL_SOFTCLOCK] =
    110  1.2  matt 		_SR_BITS_DFLT
    111  1.2  matt 	      | MIPS_SOFT_INT_MASK_0,
    112  1.2  matt 	[IPL_SOFTNET] =
    113  1.2  matt 		_SR_BITS_DFLT
    114  1.2  matt 	      | MIPS_SOFT_INT_MASK_0
    115  1.2  matt 	      | MIPS_SOFT_INT_MASK_1,
    116  1.2  matt 	[IPL_VM] =
    117  1.2  matt 		_SR_BITS_DFLT
    118  1.2  matt 	      | MIPS_SOFT_INT_MASK_0
    119  1.2  matt 	      | MIPS_SOFT_INT_MASK_1
    120  1.2  matt 	      | MIPS_INT_MASK_0,
    121  1.2  matt 	[IPL_SCHED] =
    122  1.2  matt 		MIPS_INT_MASK,
    123  1.2  matt };
    124  1.2  matt 
    125  1.2  matt /*
    126  1.2  matt  * 'IRQs' here are indiividual interrupt sources
    127  1.2  matt  * each has a slot in the Interrupt Redirection Table (IRT)
    128  1.2  matt  * in the order listed
    129  1.2  matt  *
    130  1.2  matt  * NOTE: many irq sources depend on the chip family
    131  1.2  matt  * XLS1xx vs. XLS2xx vs. XLS3xx vs. XLS6xx
    132  1.2  matt  * use the right table for the CPU that's running.
    133  1.2  matt  */
    134  1.2  matt 
    135  1.2  matt /*
    136  1.2  matt  * rmixl_irqnames_xls1xx
    137  1.2  matt  * - use for XLS1xx, XLS2xx, XLS4xx-Lite
    138  1.2  matt  */
    139  1.2  matt #define	NIRQS	32
    140  1.2  matt static const char *rmixl_irqnames_xls1xx[NIRQS] = {
    141  1.2  matt 	"int 0 (watchdog)",	/*  0 */
    142  1.2  matt 	"int 1 (timer0)",	/*  1 */
    143  1.2  matt 	"int 2 (timer1)",	/*  2 */
    144  1.2  matt 	"int 3 (timer2)",	/*  3 */
    145  1.2  matt 	"int 4 (timer3)",	/*  4 */
    146  1.2  matt 	"int 5 (timer4)",	/*  5 */
    147  1.2  matt 	"int 6 (timer5)",	/*  6 */
    148  1.2  matt 	"int 7 (timer6)",	/*  7 */
    149  1.2  matt 	"int 8 (timer7)",	/*  8 */
    150  1.2  matt 	"int 9 (uart0)",	/*  9 */
    151  1.2  matt 	"int 10 (uart1)",	/* 10 */
    152  1.2  matt 	"int 11 (i2c0)",	/* 11 */
    153  1.2  matt 	"int 12 (i2c1)",	/* 12 */
    154  1.2  matt 	"int 13 (pcmcia)",	/* 13 */
    155  1.2  matt 	"int 14 (gpio_a)",	/* 14 */
    156  1.2  matt 	"int 15 (irq15)",	/* 15 */
    157  1.2  matt 	"int 16 (bridge_tb)",	/* 16 */
    158  1.2  matt 	"int 17 (gmac0)",	/* 17 */
    159  1.2  matt 	"int 18 (gmac1)",	/* 18 */
    160  1.2  matt 	"int 19 (gmac2)",	/* 19 */
    161  1.2  matt 	"int 20 (gmac3)",	/* 20 */
    162  1.2  matt 	"int 21 (irq21)",	/* 21 */
    163  1.2  matt 	"int 22 (irq22)",	/* 22 */
    164  1.2  matt 	"int 23 (irq23)",	/* 23 */
    165  1.2  matt 	"int 24 (irq24)",	/* 24 */
    166  1.2  matt 	"int 25 (bridge_err)",	/* 25 */
    167  1.2  matt 	"int 26 (pcie_link0)",	/* 26 */
    168  1.2  matt 	"int 27 (pcie_link1)",	/* 27 */
    169  1.2  matt 	"int 28 (irq28)",	/* 28 */
    170  1.2  matt 	"int 29 (irq29)",	/* 29 */
    171  1.2  matt 	"int 30 (gpio_b)",	/* 30 */
    172  1.2  matt 	"int 31 (usb)",		/* 31 */
    173  1.2  matt };
    174  1.2  matt 
    175  1.2  matt /*
    176  1.2  matt  * rmixl_irqnames_xls4xx:
    177  1.2  matt  * - use for XLS4xx, XLS6xx
    178  1.2  matt  */
    179  1.2  matt static const char *rmixl_irqnames_xls4xx[NIRQS] = {
    180  1.2  matt 	"int 0 (watchdog)",	/*  0 */
    181  1.2  matt 	"int 1 (timer0)",	/*  1 */
    182  1.2  matt 	"int 2 (timer1)",	/*  2 */
    183  1.2  matt 	"int 3 (timer2)",	/*  3 */
    184  1.2  matt 	"int 4 (timer3)",	/*  4 */
    185  1.2  matt 	"int 5 (timer4)",	/*  5 */
    186  1.2  matt 	"int 6 (timer5)",	/*  6 */
    187  1.2  matt 	"int 7 (timer6)",	/*  7 */
    188  1.2  matt 	"int 8 (timer7)",	/*  8 */
    189  1.2  matt 	"int 9 (uart0)",	/*  9 */
    190  1.2  matt 	"int 10 (uart1)",	/* 10 */
    191  1.2  matt 	"int 11 (i2c0)",	/* 11 */
    192  1.2  matt 	"int 12 (i2c1)",	/* 12 */
    193  1.2  matt 	"int 13 (pcmcia)",	/* 13 */
    194  1.2  matt 	"int 14 (gpio_a)",	/* 14 */
    195  1.2  matt 	"int 15 (irq15)",	/* 15 */
    196  1.2  matt 	"int 16 (bridge_tb)",	/* 16 */
    197  1.2  matt 	"int 17 (gmac0)",	/* 17 */
    198  1.2  matt 	"int 18 (gmac1)",	/* 18 */
    199  1.2  matt 	"int 19 (gmac2)",	/* 19 */
    200  1.2  matt 	"int 20 (gmac3)",	/* 20 */
    201  1.2  matt 	"int 21 (irq21)",	/* 21 */
    202  1.2  matt 	"int 22 (irq22)",	/* 22 */
    203  1.2  matt 	"int 23 (irq23)",	/* 23 */
    204  1.2  matt 	"int 24 (irq24)",	/* 24 */
    205  1.2  matt 	"int 25 (bridge_err)",	/* 25 */
    206  1.2  matt 	"int 26 (pcie_link0)",	/* 26 */
    207  1.2  matt 	"int 27 (pcie_link1)",	/* 27 */
    208  1.2  matt 	"int 28 (pcie_link2)",	/* 28 */
    209  1.2  matt 	"int 29 (pcie_link3)",	/* 29 */
    210  1.2  matt 	"int 30 (gpio_b)",	/* 30 */
    211  1.2  matt 	"int 31 (usb)",		/* 31 */
    212  1.2  matt };
    213  1.2  matt 
    214  1.2  matt /*
    215  1.2  matt  * rmixl_irqnames_xls4xx:
    216  1.2  matt  * - use for unknown cpu implementation
    217  1.2  matt  */
    218  1.2  matt static const char *rmixl_irqnames_generic[NIRQS] = {
    219  1.2  matt 	"int 0",	/*  0 */
    220  1.2  matt 	"int 1",	/*  1 */
    221  1.2  matt 	"int 2",	/*  2 */
    222  1.2  matt 	"int 3",	/*  3 */
    223  1.2  matt 	"int 4",	/*  4 */
    224  1.2  matt 	"int 5",	/*  5 */
    225  1.2  matt 	"int 6",	/*  6 */
    226  1.2  matt 	"int 7",	/*  7 */
    227  1.2  matt 	"int 8",	/*  8 */
    228  1.2  matt 	"int 9",	/*  9 */
    229  1.2  matt 	"int 10",	/* 10 */
    230  1.2  matt 	"int 11",	/* 11 */
    231  1.2  matt 	"int 12",	/* 12 */
    232  1.2  matt 	"int 13",	/* 13 */
    233  1.2  matt 	"int 14",	/* 14 */
    234  1.2  matt 	"int 15",	/* 15 */
    235  1.2  matt 	"int 16",	/* 16 */
    236  1.2  matt 	"int 17",	/* 17 */
    237  1.2  matt 	"int 18",	/* 18 */
    238  1.2  matt 	"int 19",	/* 19 */
    239  1.2  matt 	"int 20",	/* 20 */
    240  1.2  matt 	"int 21",	/* 21 */
    241  1.2  matt 	"int 22",	/* 22 */
    242  1.2  matt 	"int 23",	/* 23 */
    243  1.2  matt 	"int 24",	/* 24 */
    244  1.2  matt 	"int 25",	/* 25 */
    245  1.2  matt 	"int 26",	/* 26 */
    246  1.2  matt 	"int 27",	/* 27 */
    247  1.2  matt 	"int 28",	/* 28 */
    248  1.2  matt 	"int 29",	/* 29 */
    249  1.2  matt 	"int 30",	/* 30 */
    250  1.2  matt 	"int 31",	/* 31 */
    251  1.2  matt };
    252  1.2  matt 
    253  1.2  matt /*
    254  1.2  matt  * per-IRQ event stats
    255  1.2  matt  */
    256  1.2  matt struct rmixl_irqtab {
    257  1.2  matt 	struct evcnt irq_count;
    258  1.2  matt 	void *irq_ih;
    259  1.2  matt };
    260  1.2  matt static struct rmixl_irqtab rmixl_irqtab[NIRQS];
    261  1.2  matt 
    262  1.2  matt 
    263  1.2  matt /*
    264  1.2  matt  * 'vectors' here correspond to IRT Entry vector numbers
    265  1.2  matt  * - IRT Entry vector# is bit# in EIRR
    266  1.2  matt  * - note that EIRR[7:0] == CAUSE[15:8]
    267  1.2  matt  * - we actually only use the first _IPL_N bits
    268  1.2  matt  *   (less than 8)
    269  1.2  matt  *
    270  1.2  matt  * each IRT entry gets routed to a vector
    271  1.2  matt  * (if and when that interrupt is established)
    272  1.2  matt  * the vectors are shared on a per-IPL basis
    273  1.2  matt  * which simplifies dispatch
    274  1.2  matt  *
    275  1.2  matt  * XXX use of mips64 extended IRQs is TBD
    276  1.2  matt  */
    277  1.2  matt #define	NINTRVECS	_IPL_N
    278  1.2  matt 
    279  1.2  matt /*
    280  1.2  matt  * translate IPL to vector number
    281  1.2  matt  */
    282  1.2  matt static const int rmixl_iplvec[_IPL_N] = {
    283  1.2  matt 	[IPL_NONE] = 		-1,	/* XXX */
    284  1.2  matt 	[IPL_SOFTCLOCK] =	 0,
    285  1.2  matt 	[IPL_SOFTNET] =		 1,
    286  1.2  matt 	[IPL_VM] =		 2,
    287  1.2  matt 	[IPL_SCHED] =		 3,
    288  1.2  matt };
    289  1.2  matt 
    290  1.2  matt /*
    291  1.2  matt  * list and ref count manage sharing of each vector
    292  1.2  matt  */
    293  1.2  matt struct rmixl_intrvec {
    294  1.2  matt 	LIST_HEAD(, evbmips_intrhand) iv_list;
    295  1.2  matt 	uint32_t iv_ack;
    296  1.2  matt 	rmixl_intr_trigger_t iv_trigger;
    297  1.2  matt         rmixl_intr_polarity_t iv_polarity;
    298  1.2  matt 	u_int iv_refcnt;
    299  1.2  matt };
    300  1.2  matt static struct rmixl_intrvec rmixl_intrvec[NINTRVECS];
    301  1.2  matt 
    302  1.2  matt #ifdef DIAGNOSTIC
    303  1.2  matt static int evbmips_intr_init_done;
    304  1.2  matt #endif
    305  1.2  matt 
    306  1.2  matt 
    307  1.2  matt static void rmixl_intr_irt_init(int);
    308  1.2  matt static void rmixl_intr_irt_disestablish(int);
    309  1.2  matt static void rmixl_intr_irt_establish(int, int, rmixl_intr_trigger_t,
    310  1.2  matt 		rmixl_intr_polarity_t, int);
    311  1.2  matt 
    312  1.2  matt 
    313  1.2  matt static inline void
    314  1.2  matt pic_irt_print(const char *s, const int n, u_int irq)
    315  1.2  matt {
    316  1.2  matt #ifdef IOINTR_DEBUG
    317  1.2  matt 	uint32_t c0, c1;
    318  1.2  matt 
    319  1.2  matt 	c0 = RMIXL_PICREG_READ(RMIXL_PIC_IRTENTRYC0(irq));
    320  1.2  matt 	c1 = RMIXL_PICREG_READ(RMIXL_PIC_IRTENTRYC1(irq));
    321  1.2  matt 	printf("%s:%d: irq %d: c0 %#x, c1 %#x\n", s, n, irq, c0, c1);
    322  1.2  matt #endif
    323  1.2  matt }
    324  1.2  matt 
    325  1.2  matt void
    326  1.2  matt evbmips_intr_init(void)
    327  1.2  matt {
    328  1.2  matt 	uint32_t r;
    329  1.2  matt 	int i;
    330  1.2  matt 
    331  1.2  matt 	KASSERT(cpu_rmixls(mycpu));
    332  1.2  matt 
    333  1.2  matt #ifdef DIAGNOSTIC
    334  1.2  matt 	if (evbmips_intr_init_done != 0)
    335  1.2  matt 		panic("%s: evbmips_intr_init_done %d",
    336  1.2  matt 			__func__, evbmips_intr_init_done);
    337  1.2  matt #endif
    338  1.2  matt 
    339  1.2  matt 	for (i=0; i < NIRQS; i++) {
    340  1.2  matt 		evcnt_attach_dynamic(&rmixl_irqtab[i].irq_count,
    341  1.2  matt 			EVCNT_TYPE_INTR, NULL, "rmixl", rmixl_intr_string(i));
    342  1.2  matt 		rmixl_irqtab[i].irq_ih = NULL;
    343  1.2  matt 	}
    344  1.2  matt 
    345  1.2  matt 	for (i=0; i < NINTRVECS; i++) {
    346  1.2  matt 		LIST_INIT(&rmixl_intrvec[i].iv_list);
    347  1.2  matt 		rmixl_intrvec[i].iv_ack = 0;
    348  1.2  matt 		rmixl_intrvec[i].iv_refcnt = 0;
    349  1.2  matt 	}
    350  1.2  matt 
    351  1.2  matt 	/*
    352  1.2  matt 	 * disable watchdog NMI, timers
    353  1.2  matt 	 *
    354  1.2  matt 	 * XXX
    355  1.2  matt 	 *  WATCHDOG_ENB is preserved because clearing it causes
    356  1.2  matt 	 *  hang on the XLS616 (but not on the XLS408)
    357  1.2  matt 	 */
    358  1.2  matt 	r = RMIXL_PICREG_READ(RMIXL_PIC_CONTROL);
    359  1.2  matt 	r &= RMIXL_PIC_CONTROL_RESV|RMIXL_PIC_CONTROL_WATCHDOG_ENB;
    360  1.2  matt 	RMIXL_PICREG_WRITE(RMIXL_PIC_CONTROL, r);
    361  1.2  matt 
    362  1.2  matt 	/*
    363  1.2  matt 	 * initialize all IRT Entries
    364  1.2  matt 	 */
    365  1.2  matt 	for (i=0; i < NIRQS; i++)
    366  1.2  matt 		rmixl_intr_irt_init(i);
    367  1.2  matt 
    368  1.2  matt 	/*
    369  1.2  matt 	 * establish IRT entry for mips3 clock interrupt
    370  1.2  matt 	 */
    371  1.2  matt 	rmixl_intr_irt_establish(7, IPL_CLOCK, RMIXL_INTR_LEVEL,
    372  1.2  matt 		RMIXL_INTR_HIGH, rmixl_iplvec[IPL_CLOCK]);
    373  1.2  matt 
    374  1.2  matt #ifdef DIAGNOSTIC
    375  1.2  matt 	evbmips_intr_init_done = 1;
    376  1.2  matt #endif
    377  1.2  matt }
    378  1.2  matt 
    379  1.2  matt const char *
    380  1.2  matt rmixl_intr_string(int irq)
    381  1.2  matt {
    382  1.2  matt 	const char *name;
    383  1.2  matt 
    384  1.2  matt 	if (irq < 0 || irq >= NIRQS)
    385  1.2  matt 		panic("%s: irq %d out of range, max %d",
    386  1.2  matt 			__func__, irq, NIRQS - 1);
    387  1.2  matt 
    388  1.2  matt 	switch (MIPS_PRID_IMPL(cpu_id)) {
    389  1.2  matt 	case MIPS_XLS104:
    390  1.2  matt 	case MIPS_XLS108:
    391  1.2  matt 	case MIPS_XLS204:
    392  1.2  matt 	case MIPS_XLS208:
    393  1.2  matt 	case MIPS_XLS404LITE:
    394  1.2  matt 	case MIPS_XLS408LITE:
    395  1.2  matt 		name = rmixl_irqnames_xls1xx[irq];
    396  1.2  matt 		break;
    397  1.2  matt         case MIPS_XLS404:
    398  1.2  matt         case MIPS_XLS408:
    399  1.2  matt         case MIPS_XLS416:
    400  1.2  matt         case MIPS_XLS608:
    401  1.2  matt         case MIPS_XLS616:
    402  1.2  matt 		name = rmixl_irqnames_xls4xx[irq];
    403  1.2  matt 		break;
    404  1.2  matt 	default:
    405  1.2  matt 		name = rmixl_irqnames_generic[irq];
    406  1.2  matt 		break;
    407  1.2  matt 	}
    408  1.2  matt 
    409  1.2  matt 	return name;
    410  1.2  matt }
    411  1.2  matt 
    412  1.2  matt /*
    413  1.2  matt  * rmixl_intr_irt_init
    414  1.2  matt  * - invalidate IRT Entry for irq
    415  1.2  matt  * - unmask Thread#0 in low word (assume we only have 1 thread)
    416  1.2  matt  */
    417  1.2  matt static void
    418  1.2  matt rmixl_intr_irt_init(int irq)
    419  1.2  matt {
    420  1.2  matt 	RMIXL_PICREG_WRITE(RMIXL_PIC_IRTENTRYC1(irq), 0);	/* high word */
    421  1.2  matt 	RMIXL_PICREG_WRITE(RMIXL_PIC_IRTENTRYC0(irq), 1);	/* low  word */
    422  1.2  matt }
    423  1.2  matt 
    424  1.2  matt /*
    425  1.2  matt  * rmixl_intr_irt_disestablish
    426  1.2  matt  * - invalidate IRT Entry for irq
    427  1.2  matt  * - writes to IRTENTRYC1 only; leave IRTENTRYC0 as-is
    428  1.2  matt  */
    429  1.2  matt static void
    430  1.2  matt rmixl_intr_irt_disestablish(int irq)
    431  1.2  matt {
    432  1.2  matt 	DPRINTF(("%s: irq %d, irtc1 %#x\n", __func__, irq, 0));
    433  1.2  matt 	RMIXL_PICREG_WRITE(RMIXL_PIC_IRTENTRYC1(irq), 0);	/* high word */
    434  1.2  matt }
    435  1.2  matt 
    436  1.2  matt /*
    437  1.2  matt  * rmixl_intr_irt_establish
    438  1.2  matt  * - construct and IRT Entry for irq and write to PIC
    439  1.2  matt  * - writes to IRTENTRYC1 only; assumes IRTENTRYC0 has been initialized
    440  1.2  matt  */
    441  1.2  matt static void
    442  1.2  matt rmixl_intr_irt_establish(int irq, int ipl, rmixl_intr_trigger_t trigger,
    443  1.2  matt 	rmixl_intr_polarity_t polarity, int vec)
    444  1.2  matt {
    445  1.2  matt 	uint32_t irtc1;
    446  1.2  matt 
    447  1.2  matt 	irtc1  = RMIXL_PIC_IRTENTRYC1_VALID;
    448  1.2  matt 	irtc1 |= RMIXL_PIC_IRTENTRYC1_GL;	/* local */
    449  1.2  matt 
    450  1.2  matt 	if (trigger == RMIXL_INTR_LEVEL)
    451  1.2  matt 		irtc1 |= RMIXL_PIC_IRTENTRYC1_TRG;
    452  1.2  matt 
    453  1.2  matt 	if ((polarity == RMIXL_INTR_FALLING) || (polarity == RMIXL_INTR_LOW))
    454  1.2  matt 		irtc1 |= RMIXL_PIC_IRTENTRYC1_P;
    455  1.2  matt 
    456  1.2  matt 	irtc1 |= vec;
    457  1.2  matt 
    458  1.2  matt 	/*
    459  1.2  matt 	 * write IRT Entry to PIC (high word only)
    460  1.2  matt 	 */
    461  1.2  matt 	DPRINTF(("%s: irq %d, irtc1 %#x\n", __func__, irq, irtc1));
    462  1.2  matt 	RMIXL_PICREG_WRITE(RMIXL_PIC_IRTENTRYC1(irq), irtc1);
    463  1.2  matt }
    464  1.2  matt 
    465  1.2  matt void *
    466  1.2  matt rmixl_intr_establish(int irq, int ipl, rmixl_intr_trigger_t trigger,
    467  1.2  matt 	rmixl_intr_polarity_t polarity, int (*func)(void *), void *arg)
    468  1.2  matt {
    469  1.2  matt 	struct evbmips_intrhand *ih;
    470  1.2  matt 	struct rmixl_intrvec *ivp;
    471  1.2  matt 	int vec;
    472  1.2  matt 	int s;
    473  1.2  matt 
    474  1.2  matt #ifdef DIAGNOSTIC
    475  1.2  matt 	if (evbmips_intr_init_done == 0)
    476  1.2  matt 		panic("%s: called before evbmips_intr_init", __func__);
    477  1.2  matt #endif
    478  1.2  matt 
    479  1.2  matt 	/*
    480  1.2  matt 	 * check args and assemble an IRT Entry
    481  1.2  matt 	 */
    482  1.2  matt 	if (irq < 0 || irq >= NIRQS)
    483  1.2  matt 		panic("%s: irq %d out of range, max %d",
    484  1.2  matt 			__func__, irq, NIRQS - 1);
    485  1.2  matt 	if (ipl <= 0 || ipl >= _IPL_N)
    486  1.2  matt 		panic("%s: ipl %d out of range, min %d, max %d",
    487  1.2  matt 			__func__, ipl, 1, _IPL_N - 1);
    488  1.2  matt 	if (rmixl_irqtab[irq].irq_ih != NULL)
    489  1.2  matt 		panic("%s: irq %d busy", __func__, irq);
    490  1.2  matt 
    491  1.2  matt 	switch (trigger) {
    492  1.2  matt 	case RMIXL_INTR_EDGE:
    493  1.2  matt 	case RMIXL_INTR_LEVEL:
    494  1.2  matt 		break;
    495  1.2  matt 	default:
    496  1.2  matt 		panic("%s: bad trigger %d\n", __func__, trigger);
    497  1.2  matt 	}
    498  1.2  matt 
    499  1.2  matt 	switch (polarity) {
    500  1.2  matt 	case RMIXL_INTR_RISING:
    501  1.2  matt 	case RMIXL_INTR_HIGH:
    502  1.2  matt 	case RMIXL_INTR_FALLING:
    503  1.2  matt 	case RMIXL_INTR_LOW:
    504  1.2  matt 		break;
    505  1.2  matt 	default:
    506  1.2  matt 		panic("%s: bad polarity %d\n", __func__, polarity);
    507  1.2  matt 	}
    508  1.2  matt 
    509  1.2  matt 	/*
    510  1.2  matt 	 * ipl determines which vector to use
    511  1.2  matt 	 */
    512  1.2  matt 	vec = rmixl_iplvec[ipl];
    513  1.2  matt 	DPRINTF(("%s: irq %d, ipl %d, vec %d\n", __func__, irq, ipl, vec));
    514  1.2  matt 	KASSERT((vec & ~RMIXL_PIC_IRTENTRYC1_INTVEC) == 0);
    515  1.2  matt 
    516  1.2  matt 	s = splhigh();
    517  1.2  matt 
    518  1.2  matt 	ivp = &rmixl_intrvec[vec];
    519  1.2  matt 	if (ivp->iv_refcnt == 0) {
    520  1.2  matt 		ivp->iv_trigger = trigger;
    521  1.2  matt 		ivp->iv_polarity = polarity;
    522  1.2  matt 	} else {
    523  1.2  matt 		if (ivp->iv_trigger != trigger) {
    524  1.2  matt #ifdef DIAGNOSTIC
    525  1.2  matt 			printf("%s: vec %d, irqs {", __func__, vec);
    526  1.2  matt 			LIST_FOREACH(ih, &ivp->iv_list, ih_q) {
    527  1.2  matt 				printf(" %d", ih->ih_irq);
    528  1.2  matt 			}
    529  1.2  matt 			printf(" } trigger type %d; irq %d wants type %d\n",
    530  1.2  matt 				ivp->iv_trigger, irq, trigger);
    531  1.2  matt #endif
    532  1.2  matt 			panic("%s: trigger mismatch at vec %d\n",
    533  1.2  matt 				__func__, vec);
    534  1.2  matt 		}
    535  1.2  matt 		if (ivp->iv_polarity != polarity) {
    536  1.2  matt #ifdef DIAGNOSTIC
    537  1.2  matt 			printf("%s: vec %d, irqs {", __func__, vec);
    538  1.2  matt 			LIST_FOREACH(ih, &ivp->iv_list, ih_q) {
    539  1.2  matt 				printf(" %d", ih->ih_irq);
    540  1.2  matt 			}
    541  1.2  matt 			printf(" } polarity type %d; irq %d wants type %d\n",
    542  1.2  matt 				ivp->iv_polarity, irq, polarity);
    543  1.2  matt #endif
    544  1.2  matt 			panic("%s: polarity mismatch at vec %d\n",
    545  1.2  matt 				__func__, vec);
    546  1.2  matt 		}
    547  1.2  matt 	}
    548  1.2  matt 	ivp->iv_ack |= (1 << irq);
    549  1.2  matt 
    550  1.2  matt 	/*
    551  1.2  matt 	 * allocate and initialize an interrupt handle
    552  1.2  matt 	 */
    553  1.2  matt 	ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
    554  1.2  matt 	if (ih == NULL)
    555  1.2  matt 		return NULL;
    556  1.2  matt 
    557  1.2  matt 	ih->ih_func = func;
    558  1.2  matt 	ih->ih_arg = arg;
    559  1.2  matt 	ih->ih_irq = irq;
    560  1.2  matt 	ih->ih_ipl = ipl;
    561  1.2  matt 
    562  1.2  matt 	/*
    563  1.2  matt 	 * mark this irq as established, busy
    564  1.2  matt 	 */
    565  1.2  matt 	rmixl_irqtab[irq].irq_ih = ih;
    566  1.2  matt 
    567  1.2  matt 	/*
    568  1.2  matt 	 * link this ih into the tables and bump reference count
    569  1.2  matt 	 */
    570  1.2  matt 	LIST_INSERT_HEAD(&ivp->iv_list, ih, ih_q);
    571  1.2  matt 	ivp->iv_refcnt++;
    572  1.2  matt 
    573  1.2  matt 	/*
    574  1.2  matt 	 * establish IRT Entry
    575  1.2  matt 	 */
    576  1.2  matt 	rmixl_intr_irt_establish(irq, ipl, trigger, polarity, vec);
    577  1.2  matt 
    578  1.2  matt 	splx(s);
    579  1.2  matt 
    580  1.2  matt 	return ih;
    581  1.2  matt }
    582  1.2  matt 
    583  1.2  matt void
    584  1.2  matt rmixl_intr_disestablish(void *cookie)
    585  1.2  matt {
    586  1.2  matt 	struct evbmips_intrhand *ih = cookie;
    587  1.2  matt 	struct rmixl_intrvec *ivp;
    588  1.2  matt 	int irq;
    589  1.2  matt 	int vec;
    590  1.2  matt 	int s;
    591  1.2  matt 
    592  1.2  matt 	irq = ih->ih_irq;
    593  1.2  matt 	vec = rmixl_iplvec[ih->ih_ipl];
    594  1.2  matt 	ivp = &rmixl_intrvec[vec];
    595  1.2  matt 
    596  1.2  matt 	s = splhigh();
    597  1.2  matt 
    598  1.2  matt 	/*
    599  1.2  matt 	 * disable the IRT Entry (high word only)
    600  1.2  matt 	 */
    601  1.2  matt 	rmixl_intr_irt_disestablish(irq);
    602  1.2  matt 
    603  1.2  matt 	/*
    604  1.2  matt 	 * remove from the table and adjust the reference count
    605  1.2  matt 	 */
    606  1.2  matt 	LIST_REMOVE(ih, ih_q);
    607  1.2  matt 	ivp->iv_refcnt--;
    608  1.2  matt 	ivp->iv_ack &= ~(1 << irq);
    609  1.2  matt 
    610  1.2  matt 	/*
    611  1.2  matt 	 * this irq now disestablished, not busy
    612  1.2  matt 	 */
    613  1.2  matt 	rmixl_irqtab[irq].irq_ih = NULL;
    614  1.2  matt 
    615  1.2  matt 	splx(s);
    616  1.2  matt 
    617  1.2  matt 	free(ih, M_DEVBUF);
    618  1.2  matt }
    619  1.2  matt 
    620  1.2  matt static inline void
    621  1.2  matt pci_int_status(const char *s, const int n)
    622  1.2  matt {
    623  1.2  matt #ifdef IOINTR_DEBUG
    624  1.2  matt 	uint32_t r;
    625  1.2  matt 	r = RMIXL_IOREG_READ(RMIXL_IO_DEV_PCIE_LE + 0xa0);
    626  1.2  matt 	printf("%s:%d: PCIE_LINK0_INT_STATUS0 %#x\n", s, n, r);
    627  1.2  matt #endif
    628  1.2  matt }
    629  1.2  matt 
    630  1.2  matt void
    631  1.2  matt evbmips_iointr(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipending)
    632  1.2  matt {
    633  1.2  matt 	struct evbmips_intrhand *ih;
    634  1.2  matt 	struct rmixl_intrvec *ivp;
    635  1.2  matt 	int vec;
    636  1.2  matt 	uint64_t eirr;
    637  1.2  matt #ifdef IOINTR_DEBUG
    638  1.2  matt 	uint64_t eimr;
    639  1.2  matt 
    640  1.2  matt 	printf("%s: status %#x, cause %#x, pc %#x, ipending %#x\n",
    641  1.2  matt 		__func__, status, cause, pc, ipending);
    642  1.2  matt 
    643  1.2  matt 	asm volatile("dmfc0 %0, $9, 6;" : "=r"(eirr));
    644  1.2  matt 	asm volatile("dmfc0 %0, $9, 7;" : "=r"(eimr));
    645  1.2  matt 	printf("%s:%d: eirr %#lx, eimr %#lx\n", __func__, __LINE__, eirr, eimr);
    646  1.2  matt 	pci_int_status(__func__, __LINE__);
    647  1.2  matt #endif
    648  1.2  matt 
    649  1.2  matt 	for (vec = NINTRVECS - 1; vec >= 2; vec--) {
    650  1.2  matt 		if ((ipending & (MIPS_SOFT_INT_MASK_0 << vec)) == 0)
    651  1.2  matt 			continue;
    652  1.2  matt 
    653  1.2  matt 		ivp = &rmixl_intrvec[vec];
    654  1.2  matt 
    655  1.2  matt 		eirr = 1ULL << vec;
    656  1.2  matt 		asm volatile("dmtc0 %0, $9, 6;" :: "r"(eirr));
    657  1.2  matt 
    658  1.2  matt #ifdef IOINTR_DEBUG
    659  1.2  matt 		printf("%s: interrupt at vec %d\n",
    660  1.2  matt 			__func__, vec);
    661  1.2  matt 		if (LIST_EMPTY(&ivp->iv_list))
    662  1.2  matt 			printf("%s: unexpected interrupt at vec %d\n",
    663  1.2  matt 				__func__, vec);
    664  1.2  matt #endif
    665  1.2  matt 		LIST_FOREACH(ih, &ivp->iv_list, ih_q) {
    666  1.2  matt 			pic_irt_print(__func__, __LINE__, ih->ih_irq);
    667  1.2  matt 			RMIXL_PICREG_WRITE(RMIXL_PIC_INTRACK,
    668  1.2  matt 				(1 << ih->ih_irq));
    669  1.2  matt 			if ((*ih->ih_func)(ih->ih_arg) != 0) {
    670  1.2  matt 				rmixl_irqtab[ih->ih_irq].irq_count.ev_count++;
    671  1.2  matt 			}
    672  1.2  matt 		}
    673  1.2  matt 
    674  1.2  matt 		pci_int_status(__func__, __LINE__);
    675  1.2  matt 
    676  1.2  matt 		cause &= ~(MIPS_SOFT_INT_MASK_0 << vec);
    677  1.2  matt 	}
    678  1.2  matt 
    679  1.2  matt 
    680  1.2  matt 	/* Re-enable anything that we have processed. */
    681  1.2  matt 	_splset(MIPS_SR_INT_IE | ((status & ~cause) & MIPS_HARD_INT_MASK));
    682  1.2  matt }
    683  1.2  matt 
    684  1.2  matt #ifdef DEBUG
    685  1.2  matt int rmixl_intrvec_print(void);
    686  1.2  matt int
    687  1.2  matt rmixl_intrvec_print(void)
    688  1.2  matt {
    689  1.2  matt 	struct evbmips_intrhand *ih;
    690  1.2  matt 	struct rmixl_intrvec *ivp;
    691  1.2  matt 	int vec;
    692  1.2  matt 
    693  1.2  matt 	ivp = &rmixl_intrvec[0];
    694  1.2  matt 	for (vec=0; vec < NINTRVECS ; vec++) {
    695  1.2  matt 		printf("vec %d, irqs {", vec);
    696  1.2  matt 		LIST_FOREACH(ih, &ivp->iv_list, ih_q)
    697  1.2  matt 			printf(" %d", ih->ih_irq);
    698  1.2  matt 		printf(" } trigger type %d\n", ivp->iv_trigger);
    699  1.2  matt 		ivp++;
    700  1.2  matt 	}
    701  1.2  matt 	return 0;
    702  1.2  matt }
    703  1.2  matt #endif
    704