2 * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
16 * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/systm.h>
36 #include <sys/interrupt.h>
37 #include <sys/kernel.h>
39 #include <machine/cpu.h>
40 #include <machine/cpufunc.h>
41 #include <machine/cpuinfo.h>
42 #include <machine/cpuregs.h>
43 #include <machine/frame.h>
44 #include <machine/intr_machdep.h>
45 #include <machine/md_var.h>
46 #include <machine/trap.h>
47 #include <machine/hwfunc.h>
49 #include <mips/nlm/hal/haldefs.h>
50 #include <mips/nlm/hal/iomap.h>
51 #include <mips/nlm/hal/mips-extns.h>
52 #include <mips/nlm/interrupt.h>
53 #include <mips/nlm/hal/pic.h>
54 #include <mips/nlm/xlp.h>
57 void (*busack)(int); /* Additional ack */
58 struct intr_event *ie; /* event corresponding to intr */
62 static struct xlp_intrsrc xlp_interrupts[XLR_MAX_INTR];
63 static mips_intrcnt_t mips_intr_counters[XLR_MAX_INTR];
64 static int intrcnt_index;
67 xlp_enable_irq(int irq)
71 eimr = nlm_read_c0_eimr();
72 nlm_write_c0_eimr(eimr | (1ULL << irq));
76 cpu_establish_softintr(const char *name, driver_filter_t * filt,
77 void (*handler) (void *), void *arg, int irq, int flags,
81 panic("Soft interrupts unsupported!\n");
85 cpu_establish_hardintr(const char *name, driver_filter_t * filt,
86 void (*handler) (void *), void *arg, int irq, int flags,
90 xlp_establish_intr(name, filt, handler, arg, irq, flags,
95 xlp_post_filter(void *source)
97 struct xlp_intrsrc *src = source;
100 src->busack(src->irq);
101 nlm_pic_ack(xlp_pic_base, xlp_irq_to_irt(src->irq));
105 xlp_pre_ithread(void *source)
107 struct xlp_intrsrc *src = source;
110 src->busack(src->irq);
114 xlp_post_ithread(void *source)
116 struct xlp_intrsrc *src = source;
118 nlm_pic_ack(xlp_pic_base, xlp_irq_to_irt(src->irq));
122 xlp_establish_intr(const char *name, driver_filter_t filt,
123 driver_intr_t handler, void *arg, int irq, int flags,
124 void **cookiep, void (*busack)(int))
126 struct intr_event *ie; /* descriptor for the IRQ */
127 struct xlp_intrsrc *src = NULL;
130 if (irq < 0 || irq > XLR_MAX_INTR)
131 panic("%s called for unknown hard intr %d", __func__, irq);
134 * FIXME locking - not needed now, because we do this only on
137 src = &xlp_interrupts[irq];
141 * PIC based interrupts need ack in PIC, and some SoC
142 * components need additional acks (e.g. PCI)
144 if (XLP_IRQ_IS_PICINTR(irq))
145 errcode = intr_event_create(&ie, src, 0, irq,
146 xlp_pre_ithread, xlp_post_ithread, xlp_post_filter,
147 NULL, "hard intr%d:", irq);
150 panic("Unsupported non filter percpu intr %d", irq);
151 errcode = intr_event_create(&ie, src, 0, irq,
152 NULL, NULL, NULL, NULL, "hard intr%d:", irq);
155 printf("Could not create event for intr %d\n", irq);
159 src->busack = busack;
162 intr_event_add_handler(ie, name, filt, handler, arg,
163 intr_priority(flags), flags, cookiep);
168 cpu_intr(struct trapframe *tf)
170 struct intr_event *ie;
176 /* find a list of enabled interrupts */
177 eirr = nlm_read_c0_eirr();
178 eimr = nlm_read_c0_eimr();
186 * No need to clear the EIRR here as the handler writes to
187 * compare which ACKs the interrupt.
189 if (eirr & (1 << IRQ_TIMER)) {
190 intr_event_handle(xlp_interrupts[IRQ_TIMER].ie, tf);
195 /* FIXME sched pin >? LOCK>? */
196 for (i = sizeof(eirr) * 8 - 1; i >= 0; i--) {
197 if ((eirr & (1ULL << i)) == 0)
200 ie = xlp_interrupts[i].ie;
201 /* Don't account special IRQs */
207 mips_intrcnt_inc(mips_intr_counters[i]);
210 /* Ack the IRQ on the CPU */
211 nlm_write_c0_eirr(1ULL << i);
212 if (intr_event_handle(ie, tf) != 0) {
213 printf("stray interrupt %d\n", i);
220 mips_intrcnt_setname(mips_intrcnt_t counter, const char *name)
222 int idx = counter - intrcnt;
224 KASSERT(counter != NULL, ("mips_intrcnt_setname: NULL counter"));
226 snprintf(intrnames + (MAXCOMLEN + 1) * idx,
227 MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name);
231 mips_intrcnt_create(const char* name)
233 mips_intrcnt_t counter = &intrcnt[intrcnt_index++];
235 mips_intrcnt_setname(counter, name);
240 cpu_init_interrupts()
243 char name[MAXCOMLEN + 1];
246 * Initialize all available vectors so spare IRQ
247 * would show up in systat output
249 for (i = 0; i < XLR_MAX_INTR; i++) {
250 snprintf(name, MAXCOMLEN + 1, "int%d:", i);
251 mips_intr_counters[i] = mips_intrcnt_create(name);