1220297Sadrian/* $NetBSD: obio.c,v 1.11 2003/07/15 00:25:05 lukem Exp $ */ 2220297Sadrian 3220297Sadrian/*- 4220297Sadrian * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc. 5220297Sadrian * All rights reserved. 6220297Sadrian * 7220297Sadrian * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8220297Sadrian * 9220297Sadrian * Redistribution and use in source and binary forms, with or without 10220297Sadrian * modification, are permitted provided that the following conditions 11220297Sadrian * are met: 12220297Sadrian * 1. Redistributions of source code must retain the above copyright 13220297Sadrian * notice, this list of conditions and the following disclaimer. 14220297Sadrian * 2. Redistributions in binary form must reproduce the above copyright 15220297Sadrian * notice, this list of conditions and the following disclaimer in the 16220297Sadrian * documentation and/or other materials provided with the distribution. 17220297Sadrian * 18220297Sadrian * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 19220297Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20220297Sadrian * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21220297Sadrian * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 22220297Sadrian * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23220297Sadrian * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24220297Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25220297Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26220297Sadrian * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27220297Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28220297Sadrian * POSSIBILITY OF SUCH DAMAGE. 29220297Sadrian */ 30220297Sadrian 31220297Sadrian#include <sys/cdefs.h> 32220297Sadrian__FBSDID("$FreeBSD: releng/10.3/sys/mips/rt305x/obio.c 265999 2014-05-14 01:35:43Z ian $"); 33220297Sadrian 34220297Sadrian#include <sys/param.h> 35220297Sadrian#include <sys/systm.h> 36220297Sadrian#include <sys/bus.h> 37220297Sadrian#include <sys/interrupt.h> 38220297Sadrian#include <sys/kernel.h> 39220297Sadrian#include <sys/module.h> 40220297Sadrian#include <sys/rman.h> 41220297Sadrian#include <sys/malloc.h> 42220297Sadrian 43220297Sadrian#include <machine/bus.h> 44220297Sadrian 45220297Sadrian#include <mips/rt305x/rt305xreg.h> 46220297Sadrian#include <mips/rt305x/obiovar.h> 47220297Sadrian#include <mips/rt305x/rt305x_icvar.h> 48220297Sadrian 49220297Sadrian/* MIPS HW interrupts of IRQ/FIQ respectively */ 50220297Sadrian#define RT305X_INTR 0 51220297Sadrian#define RT305X_FAST_INTR 1 52220297Sadrian 53220297Sadrian/* Interrupt levels */ 54220297Sadrian#define INTR_IRQ 0 55220297Sadrian#define INTR_FIQ 1 56220297Sadrian 57220297Sadrian 58220297Sadrianint irq_priorities[NIRQS] = { 59220297Sadrian INTR_IRQ, /* SYSCTL */ 60220297Sadrian INTR_FIQ, /* TIMER0 */ 61220297Sadrian INTR_FIQ, /* WDTIMER */ 62220297Sadrian INTR_IRQ, /* Illegal Access */ 63220297Sadrian INTR_IRQ, /* PCM */ 64220297Sadrian INTR_IRQ, /* UART */ 65220297Sadrian INTR_IRQ, /* GPIO */ 66220297Sadrian INTR_FIQ, /* GDMA */ 67220297Sadrian INTR_IRQ, /* NAND */ 68220297Sadrian INTR_IRQ, /* Perfomance Counter */ 69220297Sadrian INTR_IRQ, /* I2S */ 70220297Sadrian INTR_IRQ, /* unknown */ 71220297Sadrian INTR_IRQ, /* UARTLITE */ 72220297Sadrian INTR_IRQ, /* unknown */ 73220297Sadrian INTR_IRQ, /* unknown */ 74220297Sadrian INTR_IRQ, /* unknown */ 75220297Sadrian INTR_IRQ, /* unknown */ 76220297Sadrian INTR_IRQ, /* EtherNet Switch */ 77220297Sadrian INTR_FIQ, /* OTG */ 78220297Sadrian INTR_IRQ, /* unknown */ 79220297Sadrian INTR_IRQ, /* unknown */ 80220297Sadrian INTR_IRQ, /* unknown */ 81220297Sadrian INTR_IRQ, /* unknown */ 82220297Sadrian INTR_IRQ, /* unknown */ 83220297Sadrian INTR_IRQ, /* unknown */ 84220297Sadrian INTR_IRQ, /* unknown */ 85220297Sadrian INTR_IRQ, /* unknown */ 86220297Sadrian INTR_IRQ, /* unknown */ 87220297Sadrian INTR_IRQ, /* unknown */ 88220297Sadrian INTR_IRQ, /* unknown */ 89220297Sadrian INTR_IRQ, /* unknown */ 90220297Sadrian INTR_IRQ, /* unknown */ 91220297Sadrian}; 92220297Sadrian 93220297Sadrian 94220297Sadrian#define REG_READ(o) *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(INTCTL_BASE + (o))) 95220297Sadrian#define REG_WRITE(o,v) (REG_READ(o)) = (v) 96220297Sadrian 97220297Sadrianstatic int obio_activate_resource(device_t, device_t, int, int, 98220297Sadrian struct resource *); 99220297Sadrianstatic device_t obio_add_child(device_t, u_int, const char *, int); 100220297Sadrianstatic struct resource * 101220297Sadrian obio_alloc_resource(device_t, device_t, int, int *, u_long, 102220297Sadrian u_long, u_long, u_int); 103220297Sadrianstatic int obio_attach(device_t); 104220297Sadrianstatic int obio_deactivate_resource(device_t, device_t, int, int, 105220297Sadrian struct resource *); 106220297Sadrianstatic struct resource_list * 107220297Sadrian obio_get_resource_list(device_t, device_t); 108220297Sadrianstatic void obio_add_res_child(device_t, const char *, int, long, int, int); 109220297Sadrianstatic void obio_hinted_child(device_t, const char *, int); 110220297Sadrianstatic int obio_intr(void *); 111220297Sadrianstatic int obio_probe(device_t); 112220297Sadrianstatic int obio_release_resource(device_t, device_t, int, int, 113220297Sadrian struct resource *); 114220297Sadrianstatic int obio_setup_intr(device_t, device_t, struct resource *, int, 115220297Sadrian driver_filter_t *, driver_intr_t *, void *, void **); 116220297Sadrianstatic int obio_teardown_intr(device_t, device_t, struct resource *, 117220297Sadrian void *); 118220297Sadrian 119220297Sadrianstatic void 120220297Sadrianobio_mask_irq(void *source) 121220297Sadrian{ 122220297Sadrian int irq; 123220297Sadrian uint32_t irqmask; 124220297Sadrian 125220297Sadrian irq = (int)source; 126220297Sadrian irqmask = 1 << irq; 127220297Sadrian 128220297Sadrian /* disable IRQ */ 129220297Sadrian rt305x_ic_set(IC_INT_DIS, irqmask); 130220297Sadrian} 131220297Sadrian 132220297Sadrianstatic void 133220297Sadrianobio_unmask_irq(void *source) 134220297Sadrian{ 135220297Sadrian int irq; 136220297Sadrian uint32_t irqmask; 137220297Sadrian 138220297Sadrian irq = (int)source; 139220297Sadrian irqmask = 1 << irq; 140220297Sadrian 141220297Sadrian /* enable IRQ */ 142220297Sadrian rt305x_ic_set(IC_INT_ENA, irqmask); 143220297Sadrian 144220297Sadrian} 145220297Sadrian 146220297Sadrian 147220297Sadrianstatic int 148220297Sadrianobio_probe(device_t dev) 149220297Sadrian{ 150220297Sadrian 151265999Sian return (BUS_PROBE_NOWILDCARD); 152220297Sadrian} 153220297Sadrian 154220297Sadrianstatic int 155220297Sadrianobio_attach(device_t dev) 156220297Sadrian{ 157220297Sadrian struct obio_softc *sc = device_get_softc(dev); 158220297Sadrian int rid; 159220297Sadrian 160220297Sadrian sc->oba_mem_rman.rm_type = RMAN_ARRAY; 161220297Sadrian sc->oba_mem_rman.rm_descr = "OBIO memory"; 162220297Sadrian if (rman_init(&sc->oba_mem_rman) != 0 || 163220297Sadrian rman_manage_region(&sc->oba_mem_rman, OBIO_MEM_START, 164220297Sadrian OBIO_MEM_END) != 0) 165220297Sadrian panic("obio_attach: failed to set up I/O rman"); 166220297Sadrian 167220297Sadrian sc->oba_irq_rman.rm_type = RMAN_ARRAY; 168220297Sadrian sc->oba_irq_rman.rm_descr = "OBIO IRQ"; 169220297Sadrian if (rman_init(&sc->oba_irq_rman) != 0 || 170220297Sadrian rman_manage_region(&sc->oba_irq_rman, 0, NIRQS-1) != 0) 171220297Sadrian panic("obio_attach: failed to set up IRQ rman"); 172220297Sadrian 173220297Sadrian /* Hook up our interrupt handler. */ 174220297Sadrian if ((sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 175220297Sadrian RT305X_INTR, RT305X_INTR, 1, 176220297Sadrian RF_SHAREABLE | RF_ACTIVE)) == NULL) { 177220297Sadrian device_printf(dev, "unable to allocate IRQ resource\n"); 178220297Sadrian return (ENXIO); 179220297Sadrian } 180220297Sadrian 181220297Sadrian if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC, obio_intr, NULL, 182220297Sadrian sc, &sc->sc_ih))) { 183220297Sadrian device_printf(dev, 184220297Sadrian "WARNING: unable to register interrupt handler\n"); 185220297Sadrian return (ENXIO); 186220297Sadrian } 187220297Sadrian 188220297Sadrian /* Hook up our FAST interrupt handler. */ 189220297Sadrian if ((sc->sc_fast_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 190220297Sadrian RT305X_FAST_INTR, RT305X_FAST_INTR, 1, 191220297Sadrian RF_SHAREABLE | RF_ACTIVE)) == NULL) { 192220297Sadrian device_printf(dev, "unable to allocate IRQ resource\n"); 193220297Sadrian return (ENXIO); 194220297Sadrian } 195220297Sadrian 196220297Sadrian if ((bus_setup_intr(dev, sc->sc_fast_irq, INTR_TYPE_MISC, obio_intr, 197220297Sadrian NULL, sc, &sc->sc_fast_ih))) { 198220297Sadrian device_printf(dev, 199220297Sadrian "WARNING: unable to register interrupt handler\n"); 200220297Sadrian return (ENXIO); 201220297Sadrian } 202220297Sadrian 203220297Sadrian /* disable all interrupts */ 204220297Sadrian rt305x_ic_set(IC_INT_DIS, IC_INT_MASK|IC_LINE_GLOBAL); 205220297Sadrian 206220297Sadrian bus_generic_probe(dev); 207220297Sadrian 208220297Sadrian obio_add_res_child(dev, "rt305x_sysctl", 0, 209220297Sadrian SYSCTL_BASE, (SYSCTL_END - SYSCTL_BASE + 1), 210220297Sadrian IC_SYSCTL); 211220297Sadrian obio_add_res_child(dev, "rt305x_ic", 0, 212220297Sadrian INTCTL_BASE, (INTCTL_END - INTCTL_BASE + 1), 213220297Sadrian -1); 214220297Sadrian#ifdef notyet 215220297Sadrian obio_add_res_child(dev, "timer",0, 216220297Sadrian TIMER_BASE, (TIMER_END - TIMER_BASE + 1), 217220297Sadrian IC_TIMER0); 218220297Sadrian obio_add_res_child(dev, "rt305x_memc", 0, 219220297Sadrian MEMCTRL_BASE, (MEMCTRL_END - MEMCTRL_BASE + 1), 220220297Sadrian -1); 221220297Sadrian obio_add_res_child(dev, "pcm", 0, 222220297Sadrian PCM_BASE, (PCM_END - PCM_BASE + 1), 223220297Sadrian IC_PCM); 224220297Sadrian obio_add_res_child(dev, "uart", 0, 225220297Sadrian UART_BASE, (UART_END - UART_BASE + 1), 226220297Sadrian IC_UART); 227220297Sadrian#endif 228220297Sadrian obio_add_res_child(dev, "gpio", 0, 229220297Sadrian PIO_BASE, (PIO_END - PIO_BASE + 1), 230220297Sadrian IC_PIO); 231220297Sadrian#ifdef notyet 232220297Sadrian obio_add_res_child(dev, "rt305x_dma", 0, 233220297Sadrian GDMA_BASE, (GDMA_END - GDMA_BASE + 1), 234220297Sadrian IC_DMA); 235220297Sadrian obio_add_res_child(dev, "rt305x_nandc", 0, 236220297Sadrian NANDFC_BASE, (NANDFC_END - NANDFC_BASE + 1), 237220297Sadrian IC_NAND); 238220297Sadrian obio_add_res_child(dev, "i2c", 0, 239220297Sadrian I2C_BASE, (I2C_END - I2C_BASE + 1), 240220297Sadrian -1); 241220297Sadrian obio_add_res_child(dev, "i2s", 0, 242220297Sadrian I2S_BASE, (I2S_END - I2S_BASE + 1), 243220297Sadrian IC_I2S); 244220297Sadrian obio_add_res_child(dev, "spi", 0, 245220297Sadrian SPI_BASE, (SPI_END - SPI_BASE + 1), 246220297Sadrian -1); 247220297Sadrian#endif 248220297Sadrian obio_add_res_child(dev, "uart", 1, 249220297Sadrian UARTLITE_BASE, (UARTLITE_END - UARTLITE_BASE + 1), 250220297Sadrian IC_UARTLITE); 251220297Sadrian obio_add_res_child(dev, "cfi", 0, 252220297Sadrian FLASH_BASE, (FLASH_END - FLASH_BASE + 1), 253220297Sadrian -1); 254220297Sadrian obio_add_res_child(dev, "dotg", 0, 255220297Sadrian USB_OTG_BASE, (USB_OTG_END - USB_OTG_BASE + 1), 256220297Sadrian IC_OTG); 257220297Sadrian obio_add_res_child(dev, "switch", 0, 258220297Sadrian ETHSW_BASE, (ETHSW_END - ETHSW_BASE + 1), 259220297Sadrian IC_ETHSW); 260220297Sadrian 261220297Sadrian bus_enumerate_hinted_children(dev); 262220297Sadrian bus_generic_attach(dev); 263220297Sadrian 264220297Sadrian /* enable IC */ 265220297Sadrian rt305x_ic_set(IC_INT_ENA, IC_LINE_GLOBAL); 266220297Sadrian 267220297Sadrian return (0); 268220297Sadrian} 269220297Sadrian 270220297Sadrianstatic struct resource * 271220297Sadrianobio_alloc_resource(device_t bus, device_t child, int type, int *rid, 272220297Sadrian u_long start, u_long end, u_long count, u_int flags) 273220297Sadrian{ 274220297Sadrian struct obio_softc *sc = device_get_softc(bus); 275220297Sadrian struct obio_ivar *ivar = device_get_ivars(child); 276220297Sadrian struct resource *rv; 277220297Sadrian struct resource_list_entry *rle; 278220297Sadrian struct rman *rm; 279220297Sadrian int isdefault, needactivate, passthrough; 280220297Sadrian 281220297Sadrian isdefault = (start == 0UL && end == ~0UL && count == 1); 282220297Sadrian needactivate = flags & RF_ACTIVE; 283220297Sadrian passthrough = (device_get_parent(child) != bus); 284220297Sadrian rle = NULL; 285220297Sadrian 286220297Sadrian if (passthrough) 287220297Sadrian return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, 288220297Sadrian rid, start, end, count, flags)); 289220297Sadrian 290220297Sadrian /* 291220297Sadrian * If this is an allocation of the "default" range for a given RID, 292220297Sadrian * and we know what the resources for this device are (ie. they aren't 293220297Sadrian * maintained by a child bus), then work out the start/end values. 294220297Sadrian */ 295220297Sadrian if (isdefault) { 296220297Sadrian rle = resource_list_find(&ivar->resources, type, *rid); 297220297Sadrian if (rle == NULL) 298220297Sadrian return (NULL); 299220297Sadrian if (rle->res != NULL) { 300220297Sadrian panic("%s: resource entry is busy", __func__); 301220297Sadrian } 302220297Sadrian start = rle->start; 303220297Sadrian end = rle->end; 304220297Sadrian count = rle->count; 305220297Sadrian } 306220297Sadrian 307220297Sadrian switch (type) { 308220297Sadrian case SYS_RES_IRQ: 309220297Sadrian rm = &sc->oba_irq_rman; 310220297Sadrian break; 311220297Sadrian case SYS_RES_MEMORY: 312220297Sadrian rm = &sc->oba_mem_rman; 313220297Sadrian break; 314220297Sadrian default: 315220297Sadrian printf("%s: unknown resource type %d\n", __func__, type); 316220297Sadrian return (0); 317220297Sadrian } 318220297Sadrian 319220297Sadrian rv = rman_reserve_resource(rm, start, end, count, flags, child); 320220297Sadrian if (rv == 0) { 321220297Sadrian printf("%s: could not reserve resource\n", __func__); 322220297Sadrian return (0); 323220297Sadrian } 324220297Sadrian 325220297Sadrian rman_set_rid(rv, *rid); 326220297Sadrian 327220297Sadrian if (needactivate) { 328220297Sadrian if (bus_activate_resource(child, type, *rid, rv)) { 329220297Sadrian printf("%s: could not activate resource\n", __func__); 330220297Sadrian rman_release_resource(rv); 331220297Sadrian return (0); 332220297Sadrian } 333220297Sadrian } 334220297Sadrian 335220297Sadrian return (rv); 336220297Sadrian} 337220297Sadrian 338220297Sadrianstatic int 339220297Sadrianobio_activate_resource(device_t bus, device_t child, int type, int rid, 340220297Sadrian struct resource *r) 341220297Sadrian{ 342220297Sadrian 343220297Sadrian /* 344220297Sadrian * If this is a memory resource, track the direct mapping 345220297Sadrian * in the uncached MIPS KSEG1 segment. 346220297Sadrian */ 347220297Sadrian if (type == SYS_RES_MEMORY) { 348220297Sadrian void *vaddr; 349220297Sadrian 350220297Sadrian vaddr = (void *)MIPS_PHYS_TO_KSEG1((intptr_t)rman_get_start(r)); 351220297Sadrian rman_set_virtual(r, vaddr); 352220297Sadrian rman_set_bustag(r, mips_bus_space_generic); 353220297Sadrian rman_set_bushandle(r, (bus_space_handle_t)vaddr); 354220297Sadrian } 355220297Sadrian 356220297Sadrian return (rman_activate_resource(r)); 357220297Sadrian} 358220297Sadrian 359220297Sadrianstatic int 360220297Sadrianobio_deactivate_resource(device_t bus, device_t child, int type, int rid, 361220297Sadrian struct resource *r) 362220297Sadrian{ 363220297Sadrian 364220297Sadrian return (rman_deactivate_resource(r)); 365220297Sadrian} 366220297Sadrian 367220297Sadrianstatic int 368220297Sadrianobio_release_resource(device_t dev, device_t child, int type, 369220297Sadrian int rid, struct resource *r) 370220297Sadrian{ 371220297Sadrian struct resource_list *rl; 372220297Sadrian struct resource_list_entry *rle; 373220297Sadrian 374220297Sadrian rl = obio_get_resource_list(dev, child); 375220297Sadrian if (rl == NULL) 376220297Sadrian return (EINVAL); 377220297Sadrian rle = resource_list_find(rl, type, rid); 378220297Sadrian if (rle == NULL) 379220297Sadrian return (EINVAL); 380220297Sadrian rman_release_resource(r); 381220297Sadrian rle->res = NULL; 382220297Sadrian 383220297Sadrian return (0); 384220297Sadrian} 385220297Sadrian 386220297Sadrianstatic int 387220297Sadrianobio_setup_intr(device_t dev, device_t child, struct resource *ires, 388220297Sadrian int flags, driver_filter_t *filt, driver_intr_t *handler, 389220297Sadrian void *arg, void **cookiep) 390220297Sadrian{ 391220297Sadrian struct obio_softc *sc = device_get_softc(dev); 392220297Sadrian struct intr_event *event; 393220297Sadrian int irq, error, priority; 394220297Sadrian uint32_t irqmask; 395220297Sadrian 396220297Sadrian irq = rman_get_start(ires); 397220297Sadrian 398220297Sadrian if (irq >= NIRQS) 399220297Sadrian panic("%s: bad irq %d", __func__, irq); 400220297Sadrian 401220297Sadrian event = sc->sc_eventstab[irq]; 402220297Sadrian if (event == NULL) { 403220297Sadrian error = intr_event_create(&event, (void *)irq, 0, irq, 404220297Sadrian obio_mask_irq, obio_unmask_irq, 405220297Sadrian NULL, NULL, "obio intr%d:", irq); 406220297Sadrian 407220297Sadrian sc->sc_eventstab[irq] = event; 408220297Sadrian } 409220297Sadrian else 410220297Sadrian panic("obio: Can't share IRQs"); 411220297Sadrian 412220297Sadrian intr_event_add_handler(event, device_get_nameunit(child), filt, 413220297Sadrian handler, arg, intr_priority(flags), flags, cookiep); 414220297Sadrian 415220297Sadrian irqmask = 1 << irq; 416220297Sadrian priority = irq_priorities[irq]; 417220297Sadrian 418220297Sadrian if (priority == INTR_FIQ) 419220297Sadrian rt305x_ic_set(IC_INTTYPE, rt305x_ic_get(IC_INTTYPE) | irqmask); 420220297Sadrian else 421220297Sadrian rt305x_ic_set(IC_INTTYPE, rt305x_ic_get(IC_INTTYPE) & ~irqmask); 422220297Sadrian 423220297Sadrian /* enable */ 424220297Sadrian obio_unmask_irq((void*)irq); 425220297Sadrian 426220297Sadrian return (0); 427220297Sadrian} 428220297Sadrian 429220297Sadrianstatic int 430220297Sadrianobio_teardown_intr(device_t dev, device_t child, struct resource *ires, 431220297Sadrian void *cookie) 432220297Sadrian{ 433220297Sadrian struct obio_softc *sc = device_get_softc(dev); 434220297Sadrian int irq, result, priority; 435220297Sadrian uint32_t irqmask; 436220297Sadrian 437220297Sadrian irq = rman_get_start(ires); 438220297Sadrian if (irq >= NIRQS) 439220297Sadrian panic("%s: bad irq %d", __func__, irq); 440220297Sadrian 441220297Sadrian if (sc->sc_eventstab[irq] == NULL) 442220297Sadrian panic("Trying to teardown unoccupied IRQ"); 443220297Sadrian 444220297Sadrian irqmask = (1 << irq); 445220297Sadrian priority = irq_priorities[irq]; 446220297Sadrian 447220297Sadrian if (priority == INTR_FIQ) 448220297Sadrian rt305x_ic_set(IC_INTTYPE, rt305x_ic_get(IC_INTTYPE) & ~irqmask); 449220297Sadrian else 450220297Sadrian rt305x_ic_set(IC_INTTYPE, rt305x_ic_get(IC_INTTYPE) | irqmask); 451220297Sadrian 452220297Sadrian /* disable */ 453220297Sadrian obio_mask_irq((void*)irq); 454220297Sadrian 455220297Sadrian result = intr_event_remove_handler(cookie); 456220297Sadrian if (!result) { 457220297Sadrian sc->sc_eventstab[irq] = NULL; 458220297Sadrian } 459220297Sadrian 460220297Sadrian return (result); 461220297Sadrian} 462220297Sadrian 463220297Sadrianstatic int 464220297Sadrianobio_intr(void *arg) 465220297Sadrian{ 466220297Sadrian struct obio_softc *sc = arg; 467220297Sadrian struct intr_event *event; 468220297Sadrian uint32_t irqstat; 469220297Sadrian int irq; 470220297Sadrian 471220297Sadrian irqstat = rt305x_ic_get(IC_IRQ0STAT); 472220297Sadrian irqstat |= rt305x_ic_get(IC_IRQ1STAT); 473220297Sadrian 474220297Sadrian irq = 0; 475220297Sadrian while (irqstat != 0) { 476220297Sadrian if ((irqstat & 1) == 1) { 477220297Sadrian event = sc->sc_eventstab[irq]; 478220297Sadrian if (!event || TAILQ_EMPTY(&event->ie_handlers)) 479220297Sadrian continue; 480220297Sadrian 481220297Sadrian /* TODO: pass frame as an argument*/ 482220297Sadrian /* TODO: log stray interrupt */ 483220297Sadrian intr_event_handle(event, NULL); 484220297Sadrian } 485220297Sadrian irq++; 486220297Sadrian irqstat >>= 1; 487220297Sadrian } 488220297Sadrian 489220297Sadrian return (FILTER_HANDLED); 490220297Sadrian} 491220297Sadrian 492220297Sadrianstatic void 493220297Sadrianobio_add_res_child(device_t bus, const char *dname, int dunit, 494220297Sadrian long maddr, int msize, int irq) 495220297Sadrian{ 496220297Sadrian device_t child; 497220297Sadrian int result; 498220297Sadrian 499220297Sadrian child = BUS_ADD_CHILD(bus, 0, dname, dunit); 500220297Sadrian 501220297Sadrian result = bus_set_resource(child, SYS_RES_MEMORY, 0, 502220297Sadrian maddr, msize); 503220297Sadrian if (result != 0) 504220297Sadrian device_printf(bus, "warning: bus_set_resource() failed\n"); 505220297Sadrian 506220297Sadrian if (irq != -1) { 507220297Sadrian result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); 508220297Sadrian if (result != 0) 509220297Sadrian device_printf(bus, 510220297Sadrian "warning: bus_set_resource() failed\n"); 511220297Sadrian } 512220297Sadrian} 513220297Sadrian 514220297Sadrianstatic void 515220297Sadrianobio_hinted_child(device_t bus, const char *dname, int dunit) 516220297Sadrian{ 517220297Sadrian long maddr; 518220297Sadrian int msize; 519220297Sadrian int irq; 520220297Sadrian 521220297Sadrian /* 522220297Sadrian * Set hard-wired resources for hinted child using 523220297Sadrian * specific RIDs. 524220297Sadrian */ 525220297Sadrian resource_long_value(dname, dunit, "maddr", &maddr); 526220297Sadrian resource_int_value(dname, dunit, "msize", &msize); 527220297Sadrian 528220297Sadrian 529220297Sadrian if (resource_int_value(dname, dunit, "irq", &irq) == 0) irq = -1; 530220297Sadrian 531220297Sadrian obio_add_res_child(bus, dname, dunit, maddr, msize, irq); 532220297Sadrian} 533220297Sadrian 534220297Sadrianstatic device_t 535220297Sadrianobio_add_child(device_t bus, u_int order, const char *name, int unit) 536220297Sadrian{ 537220297Sadrian device_t child; 538220297Sadrian struct obio_ivar *ivar; 539220297Sadrian 540220297Sadrian ivar = malloc(sizeof(struct obio_ivar), M_DEVBUF, M_WAITOK | M_ZERO); 541220297Sadrian if (ivar == NULL) { 542220297Sadrian printf("Failed to allocate ivar\n"); 543220297Sadrian return (0); 544220297Sadrian } 545220297Sadrian resource_list_init(&ivar->resources); 546220297Sadrian 547220297Sadrian child = device_add_child_ordered(bus, order, name, unit); 548220297Sadrian if (child == NULL) { 549220297Sadrian printf("Can't add child %s%d ordered\n", name, unit); 550220297Sadrian return (0); 551220297Sadrian } 552220297Sadrian 553220297Sadrian device_set_ivars(child, ivar); 554220297Sadrian 555220297Sadrian return (child); 556220297Sadrian} 557220297Sadrian 558220297Sadrian/* 559220297Sadrian * Helper routine for bus_generic_rl_get_resource/bus_generic_rl_set_resource 560220297Sadrian * Provides pointer to resource_list for these routines 561220297Sadrian */ 562220297Sadrianstatic struct resource_list * 563220297Sadrianobio_get_resource_list(device_t dev, device_t child) 564220297Sadrian{ 565220297Sadrian struct obio_ivar *ivar; 566220297Sadrian 567220297Sadrian ivar = device_get_ivars(child); 568220297Sadrian return (&(ivar->resources)); 569220297Sadrian} 570220297Sadrian 571220297Sadrianstatic int 572220297Sadrianobio_print_all_resources(device_t dev) 573220297Sadrian{ 574220297Sadrian struct obio_ivar *ivar = device_get_ivars(dev); 575220297Sadrian struct resource_list *rl = &ivar->resources; 576220297Sadrian int retval = 0; 577220297Sadrian 578220297Sadrian if (STAILQ_FIRST(rl)) 579220297Sadrian retval += printf(" at"); 580220297Sadrian 581220297Sadrian retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); 582220297Sadrian retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); 583220297Sadrian 584220297Sadrian return (retval); 585220297Sadrian} 586220297Sadrian 587220297Sadrianstatic int 588220297Sadrianobio_print_child(device_t bus, device_t child) 589220297Sadrian{ 590220297Sadrian int retval = 0; 591220297Sadrian 592220297Sadrian retval += bus_print_child_header(bus, child); 593220297Sadrian retval += obio_print_all_resources(child); 594220297Sadrian if (device_get_flags(child)) 595220297Sadrian retval += printf(" flags %#x", device_get_flags(child)); 596220297Sadrian retval += printf(" on %s\n", device_get_nameunit(bus)); 597220297Sadrian 598220297Sadrian return (retval); 599220297Sadrian} 600220297Sadrian 601220297Sadrianstatic device_method_t obio_methods[] = { 602220297Sadrian DEVMETHOD(bus_activate_resource, obio_activate_resource), 603220297Sadrian DEVMETHOD(bus_add_child, obio_add_child), 604220297Sadrian DEVMETHOD(bus_alloc_resource, obio_alloc_resource), 605220297Sadrian DEVMETHOD(bus_deactivate_resource, obio_deactivate_resource), 606220297Sadrian DEVMETHOD(bus_get_resource_list, obio_get_resource_list), 607220297Sadrian DEVMETHOD(bus_hinted_child, obio_hinted_child), 608220297Sadrian DEVMETHOD(bus_print_child, obio_print_child), 609220297Sadrian DEVMETHOD(bus_release_resource, obio_release_resource), 610220297Sadrian DEVMETHOD(bus_setup_intr, obio_setup_intr), 611220297Sadrian DEVMETHOD(bus_teardown_intr, obio_teardown_intr), 612220297Sadrian DEVMETHOD(device_attach, obio_attach), 613220297Sadrian DEVMETHOD(device_probe, obio_probe), 614220297Sadrian DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 615220297Sadrian DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), 616220297Sadrian 617220297Sadrian {0, 0}, 618220297Sadrian}; 619220297Sadrian 620220297Sadrianstatic driver_t obio_driver = { 621220297Sadrian "obio", 622220297Sadrian obio_methods, 623220297Sadrian sizeof(struct obio_softc), 624220297Sadrian}; 625220297Sadrianstatic devclass_t obio_devclass; 626220297Sadrian 627220297SadrianDRIVER_MODULE(obio, nexus, obio_driver, obio_devclass, 0, 0); 628