intr_machdep.c revision 202173
1331722Seadler/*- 299193Sjmallett * Copyright (c) 2006-2009 RMI Corporation 399193Sjmallett * Copyright (c) 2002-2004 Juli Mallett <jmallett@FreeBSD.org> 499193Sjmallett * All rights reserved. 599193Sjmallett * 699193Sjmallett * Redistribution and use in source and binary forms, with or without 799193Sjmallett * modification, are permitted provided that the following conditions 899193Sjmallett * are met: 999193Sjmallett * 1. Redistributions of source code must retain the above copyright 1099193Sjmallett * notice, this list of conditions, and the following disclaimer, 1199193Sjmallett * without modification, immediately at the beginning of the file. 1299193Sjmallett * 2. The name of the author may not be used to endorse or promote products 1399193Sjmallett * derived from this software without specific prior written permission. 1499193Sjmallett * 1599193Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1699193Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1799193Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1899193Sjmallett * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 1999193Sjmallett * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2099193Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2199193Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2299193Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2399193Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2499193Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2599193Sjmallett * SUCH DAMAGE. 2699193Sjmallett * 2799193Sjmallett */ 2899193Sjmallett 2999193Sjmallett#include <sys/cdefs.h> 3099193Sjmallett__FBSDID("$FreeBSD: head/sys/mips/rmi/intr_machdep.c 202173 2010-01-12 21:17:36Z imp $"); 3199193Sjmallett 3299193Sjmallett#include <sys/param.h> 3399193Sjmallett#include <sys/systm.h> 3499193Sjmallett#include <sys/bus.h> 3599193Sjmallett#include <sys/interrupt.h> 3699193Sjmallett#include <sys/kernel.h> 3799193Sjmallett 3899193Sjmallett#include <machine/cpu.h> 3999193Sjmallett#include <machine/cpufunc.h> 4099193Sjmallett#include <machine/cpuinfo.h> 4199193Sjmallett#include <machine/cpuregs.h> 42109506Sjmallett#include <machine/frame.h> 43109506Sjmallett#include <machine/intr_machdep.h> 4499193Sjmallett#include <machine/md_var.h> 4599193Sjmallett#include <machine/trap.h> 4699193Sjmallett#include <machine/hwfunc.h> 4799193Sjmallett#include <mips/rmi/xlrconfig.h> 4899193Sjmallett#include <mips/rmi/interrupt.h> 4999193Sjmallett#include <mips/rmi/clock.h> 5099193Sjmallett#include <mips/rmi/pic.h> 51109506Sjmallett 52109506Sjmallett/*#include <machine/intrcnt.h>*/ 53110066Sjmallettstatic mips_intrcnt_t mips_intr_counters[XLR_MAX_INTR]; 54110066Sjmallettstruct mips_intrhand mips_intr_handlers[XLR_MAX_INTR]; 55109506Sjmallettstatic int intrcnt_index; 5699193Sjmallett 5799193Sjmallettstatic void 5899193Sjmallettmips_mask_hard_irq(void *source) 59109462Sjmallett{ 6099193Sjmallett uintptr_t irq = (uintptr_t) source; 61332638Smckusick 6299193Sjmallett write_c0_eimr64(read_c0_eimr64() & ~(1ULL << irq)); 6399193Sjmallett} 6499193Sjmallett 6599193Sjmallettstatic void 66109506Sjmallettmips_unmask_hard_irq(void *source) 67109506Sjmallett{ 68109506Sjmallett uintptr_t irq = (uintptr_t) source; 69109506Sjmallett 70207141Sjeff write_c0_eimr64(read_c0_eimr64() | (1ULL << irq)); 71207141Sjeff} 72207141Sjeff 73207141Sjeffvoid 74116084Sjmallettcpu_establish_hardintr(const char *name, driver_filter_t * filt, 7599193Sjmallett void (*handler) (void *), void *arg, int irq, int flags, void **cookiep) 7699193Sjmallett{ 7799193Sjmallett struct mips_intrhand *mih; /* descriptor for the IRQ */ 7899193Sjmallett struct intr_event *ie; /* descriptor for the IRQ */ 7999193Sjmallett int errcode; 80109755Sjmallett 81116084Sjmallett if (irq < 0 || irq > XLR_MAX_INTR) 82109755Sjmallett panic("%s called for unknown hard intr %d", __func__, irq); 83109755Sjmallett 84109755Sjmallett /* 85116084Sjmallett * FIXME locking - not needed now, because we do this only on 86109755Sjmallett * startup from CPU0 87116084Sjmallett */ 88109755Sjmallett mih = &mips_intr_handlers[irq]; 89109755Sjmallett /* mih->cntp = &intrcnt[irq]; */ 90109755Sjmallett ie = mih->mih_event; 91109755Sjmallett if (ie == NULL) { 92109755Sjmallett errcode = intr_event_create(&ie, (void *)(uintptr_t) irq, 0, 93109506Sjmallett irq, mips_mask_hard_irq, mips_unmask_hard_irq, 94109506Sjmallett NULL, NULL, "hard intr%d:", irq); 95167625Spjd 96109506Sjmallett if (errcode) { 97109506Sjmallett printf("Could not create event for intr %d\n", irq); 98167625Spjd return; 9999193Sjmallett } 100109462Sjmallett } 10199222Sjmallett intr_event_add_handler(ie, name, filt, handler, arg, 102109506Sjmallett intr_priority(flags), flags, cookiep); 103167625Spjd mih->mih_event = ie; 104109506Sjmallett mips_unmask_hard_irq((void *)(uintptr_t) irq); 105109506Sjmallett} 106109506Sjmallett 107109506Sjmallett 108109506Sjmallettvoid 109167625Spjdcpu_establish_softintr(const char *name, driver_filter_t * filt, 110167625Spjd void (*handler) (void *), void *arg, int irq, int flags, 111167625Spjd void **cookiep) 112167625Spjd{ 113167625Spjd /* we don't separate them into soft/hard like other mips */ 114167625Spjd cpu_establish_hardintr(name, filt, handler, arg, irq, flags, cookiep); 115167625Spjd} 116194030Sjmallett 117194030Sjmallettvoid 118194030Sjmallettcpu_intr(struct trapframe *tf) 119194030Sjmallett{ 120167625Spjd struct mips_intrhand *mih; 121167625Spjd struct intr_event *ie; 122167625Spjd register_t eirr; 123167625Spjd int i; 124167625Spjd 125167625Spjd critical_enter(); 126167625Spjd eirr = read_c0_eirr64(); 127167625Spjd if (eirr == 0) { 128167625Spjd critical_exit(); 129167625Spjd return; 130167625Spjd } 131167625Spjd /* 132167625Spjd * No need to clear the EIRR here. the handler is gonna write to 133167625Spjd * compare which clears eirr also 134167625Spjd */ 135167625Spjd if (eirr & (1 << IRQ_TIMER)) { 136167625Spjd count_compare_clockhandler(tf); 137167625Spjd critical_exit(); 138167625Spjd return; 139167625Spjd } 140167625Spjd 141167625Spjd /* FIXME sched pin >? LOCK>? */ 142167625Spjd for (i = sizeof(eirr) * 8 - 1; i >= 0; i--) { 143167625Spjd if ((eirr & (1ULL << i)) == 0) 144167625Spjd continue; 145109506Sjmallett#ifdef SMP 146116084Sjmallett /* These are reserved interrupts */ 147109506Sjmallett if ((i == IPI_AST) || (i == IPI_RENDEZVOUS) || (i == IPI_STOP) 14899193Sjmallett || (i == IPI_SMP_CALL_FUNCTION)) { 14999193Sjmallett write_c0_eirr64(1ULL << i); 150109506Sjmallett pic_ack(i); 151116084Sjmallett smp_handle_ipi(tf, i); 15299193Sjmallett pic_delayed_ack(i); 15399193Sjmallett continue; 15499193Sjmallett } 155109509Sjmallett#ifdef XLR_PERFMON 15699193Sjmallett if (i == IPI_PERFMON) { 15799193Sjmallett write_c0_eirr64(1ULL << i); 15899823Sjmallett pic_ack(i); 15999823Sjmallett xlr_perfmon_sampler(NULL); 160109518Sjmallett pic_delayed_ack(i); 161109506Sjmallett continue; 162101687Sjmallett } 163105737Sjmallett#endif 164207141Sjeff#endif 16599193Sjmallett mih = &mips_intr_handlers[i]; 166109506Sjmallett /* atomic_add_long(mih->cntp, 1); */ 167109506Sjmallett ie = mih->mih_event; 168109506Sjmallett 169109506Sjmallett write_c0_eirr64(1ULL << i); 170116084Sjmallett pic_ack(i); 171109506Sjmallett if (!ie || TAILQ_EMPTY(&ie->ie_handlers)) { 172109506Sjmallett printf("stray interrupt %d\n", i); 173109506Sjmallett continue; 174109506Sjmallett } 175109506Sjmallett if (intr_event_handle(ie, tf) != 0) { 176116084Sjmallett printf("stray interrupt %d\n", i); 17799193Sjmallett } 178110066Sjmallett pic_delayed_ack(i); 179110066Sjmallett } 180110066Sjmallett critical_exit(); 181110066Sjmallett} 182332638Smckusick 183332638Smckusickvoid 184110066Sjmallettmips_intrcnt_setname(mips_intrcnt_t counter, const char *name) 185110066Sjmallett{ 186110066Sjmallett int idx = counter - intrcnt; 187116084Sjmallett 188110066Sjmallett KASSERT(counter != NULL, ("mips_intrcnt_setname: NULL counter")); 189332638Smckusick 190332638Smckusick snprintf(intrnames + (MAXCOMLEN + 1) * idx, 191110066Sjmallett MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name); 192116084Sjmallett} 193110066Sjmallett 194110066Sjmallettmips_intrcnt_t 195332638Smckusickmips_intrcnt_create(const char* name) 196332638Smckusick{ 197110066Sjmallett mips_intrcnt_t counter = &intrcnt[intrcnt_index++]; 198110066Sjmallett 199116084Sjmallett mips_intrcnt_setname(counter, name); 200110066Sjmallett return counter; 201} 202 203void 204cpu_init_interrupts() 205{ 206 int i; 207 char name[MAXCOMLEN + 1]; 208 209 /* 210 * Initialize all available vectors so spare IRQ 211 * would show up in systat output 212 */ 213 for (i = 0; i < XLR_MAX_INTR; i++) { 214 snprintf(name, MAXCOMLEN + 1, "int%d:", i); 215 mips_intr_counters[i] = mips_intrcnt_create(name); 216 } 217} 218