1210311Sjmallett/*- 2210311Sjmallett * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org> 3210311Sjmallett * All rights reserved. 4210311Sjmallett * 5210311Sjmallett * Redistribution and use in source and binary forms, with or without 6210311Sjmallett * modification, are permitted provided that the following conditions 7210311Sjmallett * are met: 8210311Sjmallett * 1. Redistributions of source code must retain the above copyright 9210311Sjmallett * notice, this list of conditions and the following disclaimer. 10210311Sjmallett * 2. Redistributions in binary form must reproduce the above copyright 11210311Sjmallett * notice, this list of conditions and the following disclaimer in the 12210311Sjmallett * documentation and/or other materials provided with the distribution. 13210311Sjmallett * 14210311Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15210311Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16210311Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17210311Sjmallett * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18210311Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19210311Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20210311Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21210311Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22210311Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23210311Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24210311Sjmallett * SUCH DAMAGE. 25210311Sjmallett * 26210311Sjmallett * $FreeBSD$ 27210311Sjmallett */ 28210311Sjmallett 29210311Sjmallett#include <sys/cdefs.h> 30210311Sjmallett__FBSDID("$FreeBSD$"); 31210311Sjmallett 32210311Sjmallett#include <sys/param.h> 33210311Sjmallett#include <sys/systm.h> 34210311Sjmallett#include <sys/bus.h> 35210311Sjmallett#include <sys/interrupt.h> 36210311Sjmallett#include <sys/kernel.h> 37210311Sjmallett#include <sys/module.h> 38210311Sjmallett#include <sys/rman.h> 39210311Sjmallett#include <sys/malloc.h> 40216092Sjmallett#include <sys/smp.h> 41210311Sjmallett 42210311Sjmallett#include <machine/bus.h> 43210311Sjmallett#include <machine/intr_machdep.h> 44210311Sjmallett 45210311Sjmallett#include <contrib/octeon-sdk/cvmx.h> 46232812Sjmallett#include <mips/cavium/octeon_irq.h> 47210311Sjmallett 48210311Sjmallett/* 49210311Sjmallett * This bus sits between devices/buses and nexus and handles CIU interrupts 50210311Sjmallett * and passes everything else through. It should really be a nexus subclass 51210311Sjmallett * or something, but for now this will be sufficient. 52210311Sjmallett */ 53210311Sjmallett 54210311Sjmallett#define CIU_IRQ_HARD (0) 55210311Sjmallett 56232812Sjmallett#define CIU_IRQ_EN0_BEGIN OCTEON_IRQ_WORKQ0 57232812Sjmallett#define CIU_IRQ_EN0_END OCTEON_IRQ_BOOTDMA 58210311Sjmallett#define CIU_IRQ_EN0_COUNT ((CIU_IRQ_EN0_END - CIU_IRQ_EN0_BEGIN) + 1) 59210311Sjmallett 60232812Sjmallett#define CIU_IRQ_EN1_BEGIN OCTEON_IRQ_WDOG0 61232812Sjmallett#define CIU_IRQ_EN1_END OCTEON_IRQ_DFM 62210311Sjmallett#define CIU_IRQ_EN1_COUNT ((CIU_IRQ_EN1_END - CIU_IRQ_EN1_BEGIN) + 1) 63210311Sjmallett 64210311Sjmallettstruct ciu_softc { 65210311Sjmallett struct rman irq_rman; 66210311Sjmallett struct resource *ciu_irq; 67210311Sjmallett}; 68210311Sjmallett 69210311Sjmallettstatic mips_intrcnt_t ciu_en0_intrcnt[CIU_IRQ_EN0_COUNT]; 70210311Sjmallettstatic mips_intrcnt_t ciu_en1_intrcnt[CIU_IRQ_EN1_COUNT]; 71210311Sjmallett 72210311Sjmallettstatic struct intr_event *ciu_en0_intr_events[CIU_IRQ_EN0_COUNT]; 73210311Sjmallettstatic struct intr_event *ciu_en1_intr_events[CIU_IRQ_EN1_COUNT]; 74210311Sjmallett 75210311Sjmallettstatic int ciu_probe(device_t); 76210311Sjmallettstatic int ciu_attach(device_t); 77210311Sjmallettstatic struct resource *ciu_alloc_resource(device_t, device_t, int, int *, 78210311Sjmallett u_long, u_long, u_long, u_int); 79210311Sjmallettstatic int ciu_setup_intr(device_t, device_t, struct resource *, 80210311Sjmallett int, driver_filter_t *, driver_intr_t *, 81210311Sjmallett void *, void **); 82213090Sjmallettstatic int ciu_teardown_intr(device_t, device_t, 83213090Sjmallett struct resource *, void *); 84216092Sjmallettstatic int ciu_bind_intr(device_t, device_t, struct resource *, 85216092Sjmallett int); 86216092Sjmallettstatic int ciu_describe_intr(device_t, device_t, 87216092Sjmallett struct resource *, void *, 88216092Sjmallett const char *); 89210311Sjmallettstatic void ciu_hinted_child(device_t, const char *, int); 90210311Sjmallett 91210311Sjmallettstatic void ciu_en0_intr_mask(void *); 92210311Sjmallettstatic void ciu_en0_intr_unmask(void *); 93216092Sjmallett#ifdef SMP 94216092Sjmallettstatic int ciu_en0_intr_bind(void *, u_char); 95216092Sjmallett#endif 96210311Sjmallett 97210311Sjmallettstatic void ciu_en1_intr_mask(void *); 98210311Sjmallettstatic void ciu_en1_intr_unmask(void *); 99216092Sjmallett#ifdef SMP 100216092Sjmallettstatic int ciu_en1_intr_bind(void *, u_char); 101216092Sjmallett#endif 102210311Sjmallett 103210311Sjmallettstatic int ciu_intr(void *); 104210311Sjmallett 105210311Sjmallettstatic int 106210311Sjmallettciu_probe(device_t dev) 107210311Sjmallett{ 108210311Sjmallett if (device_get_unit(dev) != 0) 109210311Sjmallett return (ENXIO); 110210311Sjmallett 111210311Sjmallett device_set_desc(dev, "Cavium Octeon Central Interrupt Unit"); 112265999Sian return (BUS_PROBE_NOWILDCARD); 113210311Sjmallett} 114210311Sjmallett 115210311Sjmallettstatic int 116210311Sjmallettciu_attach(device_t dev) 117210311Sjmallett{ 118210311Sjmallett char name[MAXCOMLEN + 1]; 119210311Sjmallett struct ciu_softc *sc; 120210311Sjmallett unsigned i; 121210311Sjmallett int error; 122210311Sjmallett int rid; 123210311Sjmallett 124210311Sjmallett sc = device_get_softc(dev); 125210311Sjmallett 126210311Sjmallett rid = 0; 127210311Sjmallett sc->ciu_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, CIU_IRQ_HARD, 128210311Sjmallett CIU_IRQ_HARD, 1, RF_ACTIVE); 129210311Sjmallett if (sc->ciu_irq == NULL) { 130210311Sjmallett device_printf(dev, "could not allocate irq%d\n", CIU_IRQ_HARD); 131210311Sjmallett return (ENXIO); 132210311Sjmallett } 133210311Sjmallett 134210311Sjmallett error = bus_setup_intr(dev, sc->ciu_irq, INTR_TYPE_MISC, ciu_intr, 135210311Sjmallett NULL, sc, NULL); 136210311Sjmallett if (error != 0) { 137210311Sjmallett device_printf(dev, "bus_setup_intr failed: %d\n", error); 138210311Sjmallett return (error); 139210311Sjmallett } 140210311Sjmallett 141210311Sjmallett sc->irq_rman.rm_type = RMAN_ARRAY; 142210311Sjmallett sc->irq_rman.rm_descr = "CIU IRQ"; 143210311Sjmallett 144210311Sjmallett error = rman_init(&sc->irq_rman); 145210311Sjmallett if (error != 0) 146210311Sjmallett return (error); 147210311Sjmallett 148210311Sjmallett /* 149210311Sjmallett * We have two contiguous IRQ regions, use a single rman. 150210311Sjmallett */ 151210311Sjmallett error = rman_manage_region(&sc->irq_rman, CIU_IRQ_EN0_BEGIN, 152210311Sjmallett CIU_IRQ_EN1_END); 153210311Sjmallett if (error != 0) 154210311Sjmallett return (error); 155210311Sjmallett 156210311Sjmallett for (i = 0; i < CIU_IRQ_EN0_COUNT; i++) { 157210311Sjmallett snprintf(name, sizeof name, "int%d:", i + CIU_IRQ_EN0_BEGIN); 158210311Sjmallett ciu_en0_intrcnt[i] = mips_intrcnt_create(name); 159210311Sjmallett } 160210311Sjmallett 161210311Sjmallett for (i = 0; i < CIU_IRQ_EN1_COUNT; i++) { 162210311Sjmallett snprintf(name, sizeof name, "int%d:", i + CIU_IRQ_EN1_BEGIN); 163210311Sjmallett ciu_en1_intrcnt[i] = mips_intrcnt_create(name); 164210311Sjmallett } 165210311Sjmallett 166210311Sjmallett bus_generic_probe(dev); 167210311Sjmallett bus_generic_attach(dev); 168210311Sjmallett 169210311Sjmallett return (0); 170210311Sjmallett} 171210311Sjmallett 172210311Sjmallettstatic struct resource * 173210311Sjmallettciu_alloc_resource(device_t bus, device_t child, int type, int *rid, 174210311Sjmallett u_long start, u_long end, u_long count, u_int flags) 175210311Sjmallett{ 176210311Sjmallett struct resource *res; 177210311Sjmallett struct ciu_softc *sc; 178210311Sjmallett 179210311Sjmallett sc = device_get_softc(bus); 180210311Sjmallett 181210311Sjmallett switch (type) { 182210311Sjmallett case SYS_RES_IRQ: 183210311Sjmallett break; 184210311Sjmallett default: 185210311Sjmallett return (bus_alloc_resource(device_get_parent(bus), type, rid, 186210311Sjmallett start, end, count, flags)); 187210311Sjmallett } 188210311Sjmallett 189210311Sjmallett /* 190210311Sjmallett * One interrupt at a time for now. 191210311Sjmallett */ 192210311Sjmallett if (start != end) 193210311Sjmallett return (NULL); 194210311Sjmallett 195210311Sjmallett res = rman_reserve_resource(&sc->irq_rman, start, end, count, flags, 196210311Sjmallett child); 197210311Sjmallett if (res != NULL) 198210311Sjmallett return (res); 199210311Sjmallett 200210311Sjmallett return (NULL); 201210311Sjmallett} 202210311Sjmallett 203210311Sjmallettstatic int 204210311Sjmallettciu_setup_intr(device_t bus, device_t child, struct resource *res, int flags, 205210311Sjmallett driver_filter_t *filter, driver_intr_t *intr, void *arg, 206210311Sjmallett void **cookiep) 207210311Sjmallett{ 208210311Sjmallett struct intr_event *event, **eventp; 209210311Sjmallett void (*mask_func)(void *); 210210311Sjmallett void (*unmask_func)(void *); 211216092Sjmallett int (*bind_func)(void *, u_char); 212210311Sjmallett mips_intrcnt_t intrcnt; 213210311Sjmallett int error; 214210311Sjmallett int irq; 215210311Sjmallett 216210311Sjmallett irq = rman_get_start(res); 217210311Sjmallett if (irq <= CIU_IRQ_EN0_END) { 218210311Sjmallett eventp = &ciu_en0_intr_events[irq - CIU_IRQ_EN0_BEGIN]; 219210311Sjmallett intrcnt = ciu_en0_intrcnt[irq - CIU_IRQ_EN0_BEGIN]; 220210311Sjmallett mask_func = ciu_en0_intr_mask; 221210311Sjmallett unmask_func = ciu_en0_intr_unmask; 222216092Sjmallett#ifdef SMP 223216092Sjmallett bind_func = ciu_en0_intr_bind; 224216092Sjmallett#endif 225210311Sjmallett } else { 226210311Sjmallett eventp = &ciu_en1_intr_events[irq - CIU_IRQ_EN1_BEGIN]; 227210311Sjmallett intrcnt = ciu_en1_intrcnt[irq - CIU_IRQ_EN1_BEGIN]; 228210311Sjmallett mask_func = ciu_en1_intr_mask; 229210311Sjmallett unmask_func = ciu_en1_intr_unmask; 230216092Sjmallett#ifdef SMP 231216092Sjmallett bind_func = ciu_en1_intr_bind; 232216092Sjmallett#endif 233210311Sjmallett } 234216092Sjmallett#if !defined(SMP) 235216092Sjmallett bind_func = NULL; 236216092Sjmallett#endif 237210311Sjmallett 238210311Sjmallett if ((event = *eventp) == NULL) { 239210311Sjmallett error = intr_event_create(eventp, (void *)(uintptr_t)irq, 0, 240216092Sjmallett irq, mask_func, unmask_func, NULL, bind_func, "int%d", irq); 241210311Sjmallett if (error != 0) 242210311Sjmallett return (error); 243210311Sjmallett 244210311Sjmallett event = *eventp; 245210311Sjmallett 246210311Sjmallett unmask_func((void *)(uintptr_t)irq); 247210311Sjmallett } 248210311Sjmallett 249210311Sjmallett intr_event_add_handler(event, device_get_nameunit(child), 250210311Sjmallett filter, intr, arg, intr_priority(flags), flags, cookiep); 251210311Sjmallett 252210311Sjmallett mips_intrcnt_setname(intrcnt, event->ie_fullname); 253210311Sjmallett 254210311Sjmallett return (0); 255210311Sjmallett} 256210311Sjmallett 257213090Sjmallettstatic int 258213090Sjmallettciu_teardown_intr(device_t bus, device_t child, struct resource *res, 259213090Sjmallett void *cookie) 260213090Sjmallett{ 261213090Sjmallett int error; 262213090Sjmallett 263213090Sjmallett error = intr_event_remove_handler(cookie); 264213090Sjmallett if (error != 0) 265213090Sjmallett return (error); 266213090Sjmallett 267213090Sjmallett return (0); 268213090Sjmallett} 269213090Sjmallett 270216092Sjmallett#ifdef SMP 271216092Sjmallettstatic int 272216092Sjmallettciu_bind_intr(device_t bus, device_t child, struct resource *res, int cpu) 273216092Sjmallett{ 274216092Sjmallett struct intr_event *event; 275216092Sjmallett int irq; 276216092Sjmallett 277216092Sjmallett irq = rman_get_start(res); 278216092Sjmallett if (irq <= CIU_IRQ_EN0_END) 279216092Sjmallett event = ciu_en0_intr_events[irq - CIU_IRQ_EN0_BEGIN]; 280216092Sjmallett else 281216092Sjmallett event = ciu_en1_intr_events[irq - CIU_IRQ_EN1_BEGIN]; 282216092Sjmallett 283216092Sjmallett return (intr_event_bind(event, cpu)); 284216092Sjmallett} 285216092Sjmallett#endif 286216092Sjmallett 287216092Sjmallettstatic int 288216092Sjmallettciu_describe_intr(device_t bus, device_t child, struct resource *res, 289216092Sjmallett void *cookie, const char *descr) 290216092Sjmallett{ 291216092Sjmallett struct intr_event *event; 292216092Sjmallett mips_intrcnt_t intrcnt; 293216092Sjmallett int error; 294216092Sjmallett int irq; 295216092Sjmallett 296216092Sjmallett irq = rman_get_start(res); 297216092Sjmallett if (irq <= CIU_IRQ_EN0_END) { 298216092Sjmallett event = ciu_en0_intr_events[irq - CIU_IRQ_EN0_BEGIN]; 299216092Sjmallett intrcnt = ciu_en0_intrcnt[irq - CIU_IRQ_EN0_BEGIN]; 300216092Sjmallett } else { 301216092Sjmallett event = ciu_en1_intr_events[irq - CIU_IRQ_EN1_BEGIN]; 302216092Sjmallett intrcnt = ciu_en1_intrcnt[irq - CIU_IRQ_EN1_BEGIN]; 303216092Sjmallett } 304216092Sjmallett 305216092Sjmallett error = intr_event_describe_handler(event, cookie, descr); 306216092Sjmallett if (error != 0) 307216092Sjmallett return (error); 308216092Sjmallett 309216092Sjmallett mips_intrcnt_setname(intrcnt, event->ie_fullname); 310216092Sjmallett 311216092Sjmallett return (0); 312216092Sjmallett} 313216092Sjmallett 314210311Sjmallettstatic void 315210311Sjmallettciu_hinted_child(device_t bus, const char *dname, int dunit) 316210311Sjmallett{ 317210311Sjmallett BUS_ADD_CHILD(bus, 0, dname, dunit); 318210311Sjmallett} 319210311Sjmallett 320210311Sjmallettstatic void 321210311Sjmallettciu_en0_intr_mask(void *arg) 322210311Sjmallett{ 323210311Sjmallett uint64_t mask; 324210311Sjmallett int irq; 325210311Sjmallett 326210311Sjmallett irq = (uintptr_t)arg; 327210311Sjmallett mask = cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2)); 328210311Sjmallett mask &= ~(1ull << (irq - CIU_IRQ_EN0_BEGIN)); 329210311Sjmallett cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2), mask); 330210311Sjmallett} 331210311Sjmallett 332210311Sjmallettstatic void 333210311Sjmallettciu_en0_intr_unmask(void *arg) 334210311Sjmallett{ 335210311Sjmallett uint64_t mask; 336210311Sjmallett int irq; 337210311Sjmallett 338210311Sjmallett irq = (uintptr_t)arg; 339210311Sjmallett mask = cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2)); 340210311Sjmallett mask |= 1ull << (irq - CIU_IRQ_EN0_BEGIN); 341210311Sjmallett cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2), mask); 342210311Sjmallett} 343210311Sjmallett 344216092Sjmallett#ifdef SMP 345216092Sjmallettstatic int 346216092Sjmallettciu_en0_intr_bind(void *arg, u_char target) 347216092Sjmallett{ 348216092Sjmallett uint64_t mask; 349216092Sjmallett int core; 350216092Sjmallett int irq; 351216092Sjmallett 352216092Sjmallett irq = (uintptr_t)arg; 353216092Sjmallett CPU_FOREACH(core) { 354216092Sjmallett mask = cvmx_read_csr(CVMX_CIU_INTX_EN0(core*2)); 355216092Sjmallett if (core == target) 356216092Sjmallett mask |= 1ull << (irq - CIU_IRQ_EN0_BEGIN); 357216092Sjmallett else 358216092Sjmallett mask &= ~(1ull << (irq - CIU_IRQ_EN0_BEGIN)); 359216092Sjmallett cvmx_write_csr(CVMX_CIU_INTX_EN0(core*2), mask); 360216092Sjmallett } 361216092Sjmallett 362216092Sjmallett return (0); 363216092Sjmallett} 364216092Sjmallett#endif 365216092Sjmallett 366210311Sjmallettstatic void 367210311Sjmallettciu_en1_intr_mask(void *arg) 368210311Sjmallett{ 369210311Sjmallett uint64_t mask; 370210311Sjmallett int irq; 371210311Sjmallett 372210311Sjmallett irq = (uintptr_t)arg; 373210311Sjmallett mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2)); 374210311Sjmallett mask &= ~(1ull << (irq - CIU_IRQ_EN1_BEGIN)); 375210311Sjmallett cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2), mask); 376210311Sjmallett} 377210311Sjmallett 378210311Sjmallettstatic void 379210311Sjmallettciu_en1_intr_unmask(void *arg) 380210311Sjmallett{ 381210311Sjmallett uint64_t mask; 382210311Sjmallett int irq; 383210311Sjmallett 384210311Sjmallett irq = (uintptr_t)arg; 385210311Sjmallett mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2)); 386210311Sjmallett mask |= 1ull << (irq - CIU_IRQ_EN1_BEGIN); 387210311Sjmallett cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2), mask); 388210311Sjmallett} 389210311Sjmallett 390216092Sjmallett#ifdef SMP 391210311Sjmallettstatic int 392216092Sjmallettciu_en1_intr_bind(void *arg, u_char target) 393216092Sjmallett{ 394216092Sjmallett uint64_t mask; 395216092Sjmallett int core; 396216092Sjmallett int irq; 397216092Sjmallett 398216092Sjmallett irq = (uintptr_t)arg; 399216092Sjmallett CPU_FOREACH(core) { 400216092Sjmallett mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(core*2)); 401216092Sjmallett if (core == target) 402216092Sjmallett mask |= 1ull << (irq - CIU_IRQ_EN1_BEGIN); 403216092Sjmallett else 404216092Sjmallett mask &= ~(1ull << (irq - CIU_IRQ_EN1_BEGIN)); 405216092Sjmallett cvmx_write_csr(CVMX_CIU_INTX_EN1(core*2), mask); 406216092Sjmallett } 407216092Sjmallett 408216092Sjmallett return (0); 409216092Sjmallett} 410216092Sjmallett#endif 411216092Sjmallett 412216092Sjmallettstatic int 413210311Sjmallettciu_intr(void *arg) 414210311Sjmallett{ 415210311Sjmallett struct ciu_softc *sc; 416210311Sjmallett uint64_t en0_sum, en1_sum; 417210311Sjmallett uint64_t en0_mask, en1_mask; 418210311Sjmallett int irq_index; 419210311Sjmallett int error; 420210311Sjmallett 421210311Sjmallett sc = arg; 422210311Sjmallett (void)sc; 423210311Sjmallett 424210311Sjmallett en0_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(cvmx_get_core_num()*2)); 425210311Sjmallett en1_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1); 426210311Sjmallett 427210311Sjmallett en0_mask = cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2)); 428210311Sjmallett en1_mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2)); 429210311Sjmallett 430210311Sjmallett en0_sum &= en0_mask; 431210311Sjmallett en1_sum &= en1_mask; 432210311Sjmallett 433210311Sjmallett if (en0_sum == 0 && en1_sum == 0) 434210311Sjmallett return (FILTER_STRAY); 435210311Sjmallett 436210311Sjmallett irq_index = 0; 437210311Sjmallett for (irq_index = 0; en0_sum != 0; irq_index++, en0_sum >>= 1) { 438210311Sjmallett if ((en0_sum & 1) == 0) 439210311Sjmallett continue; 440210311Sjmallett 441210311Sjmallett mips_intrcnt_inc(ciu_en0_intrcnt[irq_index]); 442210311Sjmallett 443210311Sjmallett error = intr_event_handle(ciu_en0_intr_events[irq_index], NULL); 444210311Sjmallett if (error != 0) 445210311Sjmallett printf("%s: stray en0 irq%d\n", __func__, irq_index); 446210311Sjmallett } 447210311Sjmallett 448210311Sjmallett irq_index = 0; 449210311Sjmallett for (irq_index = 0; en1_sum != 0; irq_index++, en1_sum >>= 1) { 450210311Sjmallett if ((en1_sum & 1) == 0) 451210311Sjmallett continue; 452210311Sjmallett 453210311Sjmallett mips_intrcnt_inc(ciu_en1_intrcnt[irq_index]); 454210311Sjmallett 455210311Sjmallett error = intr_event_handle(ciu_en1_intr_events[irq_index], NULL); 456210311Sjmallett if (error != 0) 457210311Sjmallett printf("%s: stray en1 irq%d\n", __func__, irq_index); 458210311Sjmallett } 459210311Sjmallett 460210311Sjmallett return (FILTER_HANDLED); 461210311Sjmallett} 462210311Sjmallett 463210311Sjmallettstatic device_method_t ciu_methods[] = { 464210311Sjmallett DEVMETHOD(device_probe, ciu_probe), 465210311Sjmallett DEVMETHOD(device_attach, ciu_attach), 466210311Sjmallett 467210311Sjmallett DEVMETHOD(bus_alloc_resource, ciu_alloc_resource), 468210311Sjmallett DEVMETHOD(bus_activate_resource,bus_generic_activate_resource), 469210311Sjmallett DEVMETHOD(bus_setup_intr, ciu_setup_intr), 470213090Sjmallett DEVMETHOD(bus_teardown_intr, ciu_teardown_intr), 471216092Sjmallett#ifdef SMP 472216092Sjmallett DEVMETHOD(bus_bind_intr, ciu_bind_intr), 473216092Sjmallett#endif 474216092Sjmallett DEVMETHOD(bus_describe_intr, ciu_describe_intr), 475210311Sjmallett 476210311Sjmallett DEVMETHOD(bus_add_child, bus_generic_add_child), 477210311Sjmallett DEVMETHOD(bus_hinted_child, ciu_hinted_child), 478210311Sjmallett 479210311Sjmallett { 0, 0 } 480210311Sjmallett}; 481210311Sjmallett 482210311Sjmallettstatic driver_t ciu_driver = { 483210311Sjmallett "ciu", 484210311Sjmallett ciu_methods, 485210311Sjmallett sizeof(struct ciu_softc), 486210311Sjmallett}; 487210311Sjmallettstatic devclass_t ciu_devclass; 488210311SjmallettDRIVER_MODULE(ciu, nexus, ciu_driver, ciu_devclass, 0, 0); 489