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$"); 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 * 101294883Sjhibbits obio_alloc_resource(device_t, device_t, int, int *, rman_res_t, 102294883Sjhibbits rman_res_t, rman_res_t, 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 151257338Snwhitehorn 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); 224292703Sadrian#endif 225220297Sadrian obio_add_res_child(dev, "uart", 0, 226220297Sadrian UART_BASE, (UART_END - UART_BASE + 1), 227220297Sadrian IC_UART); 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); 244292703Sadrian#endif 245220297Sadrian obio_add_res_child(dev, "spi", 0, 246220297Sadrian SPI_BASE, (SPI_END - SPI_BASE + 1), 247220297Sadrian -1); 248220297Sadrian obio_add_res_child(dev, "uart", 1, 249220297Sadrian UARTLITE_BASE, (UARTLITE_END - UARTLITE_BASE + 1), 250220297Sadrian IC_UARTLITE); 251292703Sadrian#if !defined(RT5350) && !defined(MT7620) 252220297Sadrian obio_add_res_child(dev, "cfi", 0, 253220297Sadrian FLASH_BASE, (FLASH_END - FLASH_BASE + 1), 254220297Sadrian -1); 255292703Sadrian obio_add_res_child(dev, "dwcotg", 0, 256220297Sadrian USB_OTG_BASE, (USB_OTG_END - USB_OTG_BASE + 1), 257220297Sadrian IC_OTG); 258292703Sadrian#else 259292703Sadrian obio_add_res_child(dev, "ehci", 0, 260292703Sadrian USB_OTG_BASE, (USB_OTG_END - USB_OTG_BASE + 1), 261292703Sadrian IC_OTG); 262292703Sadrian obio_add_res_child(dev, "ohci", 0, 263292703Sadrian USB_OHCI_BASE, (USB_OHCI_END - USB_OHCI_BASE + 1), 264292703Sadrian IC_OTG); 265292703Sadrian#endif 266220297Sadrian obio_add_res_child(dev, "switch", 0, 267220297Sadrian ETHSW_BASE, (ETHSW_END - ETHSW_BASE + 1), 268220297Sadrian IC_ETHSW); 269220297Sadrian 270220297Sadrian bus_enumerate_hinted_children(dev); 271220297Sadrian bus_generic_attach(dev); 272220297Sadrian 273220297Sadrian /* enable IC */ 274220297Sadrian rt305x_ic_set(IC_INT_ENA, IC_LINE_GLOBAL); 275220297Sadrian 276220297Sadrian return (0); 277220297Sadrian} 278220297Sadrian 279220297Sadrianstatic struct resource * 280220297Sadrianobio_alloc_resource(device_t bus, device_t child, int type, int *rid, 281294883Sjhibbits rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 282220297Sadrian{ 283220297Sadrian struct obio_softc *sc = device_get_softc(bus); 284220297Sadrian struct obio_ivar *ivar = device_get_ivars(child); 285220297Sadrian struct resource *rv; 286220297Sadrian struct resource_list_entry *rle; 287220297Sadrian struct rman *rm; 288220297Sadrian int isdefault, needactivate, passthrough; 289220297Sadrian 290295832Sjhibbits isdefault = (RMAN_IS_DEFAULT_RANGE(start, end) && count == 1); 291220297Sadrian needactivate = flags & RF_ACTIVE; 292220297Sadrian passthrough = (device_get_parent(child) != bus); 293220297Sadrian rle = NULL; 294220297Sadrian 295220297Sadrian if (passthrough) 296220297Sadrian return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, 297220297Sadrian rid, start, end, count, flags)); 298220297Sadrian 299220297Sadrian /* 300220297Sadrian * If this is an allocation of the "default" range for a given RID, 301220297Sadrian * and we know what the resources for this device are (ie. they aren't 302220297Sadrian * maintained by a child bus), then work out the start/end values. 303220297Sadrian */ 304220297Sadrian if (isdefault) { 305220297Sadrian rle = resource_list_find(&ivar->resources, type, *rid); 306220297Sadrian if (rle == NULL) 307220297Sadrian return (NULL); 308220297Sadrian if (rle->res != NULL) { 309220297Sadrian panic("%s: resource entry is busy", __func__); 310220297Sadrian } 311220297Sadrian start = rle->start; 312220297Sadrian end = rle->end; 313220297Sadrian count = rle->count; 314220297Sadrian } 315220297Sadrian 316220297Sadrian switch (type) { 317220297Sadrian case SYS_RES_IRQ: 318220297Sadrian rm = &sc->oba_irq_rman; 319220297Sadrian break; 320220297Sadrian case SYS_RES_MEMORY: 321220297Sadrian rm = &sc->oba_mem_rman; 322220297Sadrian break; 323220297Sadrian default: 324220297Sadrian printf("%s: unknown resource type %d\n", __func__, type); 325220297Sadrian return (0); 326220297Sadrian } 327220297Sadrian 328220297Sadrian rv = rman_reserve_resource(rm, start, end, count, flags, child); 329298053Spfg if (rv == NULL) { 330220297Sadrian printf("%s: could not reserve resource\n", __func__); 331220297Sadrian return (0); 332220297Sadrian } 333220297Sadrian 334220297Sadrian rman_set_rid(rv, *rid); 335220297Sadrian 336220297Sadrian if (needactivate) { 337220297Sadrian if (bus_activate_resource(child, type, *rid, rv)) { 338220297Sadrian printf("%s: could not activate resource\n", __func__); 339220297Sadrian rman_release_resource(rv); 340220297Sadrian return (0); 341220297Sadrian } 342220297Sadrian } 343220297Sadrian 344220297Sadrian return (rv); 345220297Sadrian} 346220297Sadrian 347220297Sadrianstatic int 348220297Sadrianobio_activate_resource(device_t bus, device_t child, int type, int rid, 349220297Sadrian struct resource *r) 350220297Sadrian{ 351220297Sadrian 352220297Sadrian /* 353220297Sadrian * If this is a memory resource, track the direct mapping 354220297Sadrian * in the uncached MIPS KSEG1 segment. 355220297Sadrian */ 356220297Sadrian if (type == SYS_RES_MEMORY) { 357220297Sadrian void *vaddr; 358220297Sadrian 359220297Sadrian vaddr = (void *)MIPS_PHYS_TO_KSEG1((intptr_t)rman_get_start(r)); 360220297Sadrian rman_set_virtual(r, vaddr); 361220297Sadrian rman_set_bustag(r, mips_bus_space_generic); 362220297Sadrian rman_set_bushandle(r, (bus_space_handle_t)vaddr); 363220297Sadrian } 364220297Sadrian 365220297Sadrian return (rman_activate_resource(r)); 366220297Sadrian} 367220297Sadrian 368220297Sadrianstatic int 369220297Sadrianobio_deactivate_resource(device_t bus, device_t child, int type, int rid, 370220297Sadrian struct resource *r) 371220297Sadrian{ 372220297Sadrian 373220297Sadrian return (rman_deactivate_resource(r)); 374220297Sadrian} 375220297Sadrian 376220297Sadrianstatic int 377220297Sadrianobio_release_resource(device_t dev, device_t child, int type, 378220297Sadrian int rid, struct resource *r) 379220297Sadrian{ 380220297Sadrian struct resource_list *rl; 381220297Sadrian struct resource_list_entry *rle; 382220297Sadrian 383220297Sadrian rl = obio_get_resource_list(dev, child); 384220297Sadrian if (rl == NULL) 385220297Sadrian return (EINVAL); 386220297Sadrian rle = resource_list_find(rl, type, rid); 387220297Sadrian if (rle == NULL) 388220297Sadrian return (EINVAL); 389220297Sadrian rman_release_resource(r); 390220297Sadrian rle->res = NULL; 391220297Sadrian 392220297Sadrian return (0); 393220297Sadrian} 394220297Sadrian 395220297Sadrianstatic int 396220297Sadrianobio_setup_intr(device_t dev, device_t child, struct resource *ires, 397220297Sadrian int flags, driver_filter_t *filt, driver_intr_t *handler, 398220297Sadrian void *arg, void **cookiep) 399220297Sadrian{ 400220297Sadrian struct obio_softc *sc = device_get_softc(dev); 401220297Sadrian struct intr_event *event; 402220297Sadrian int irq, error, priority; 403220297Sadrian uint32_t irqmask; 404220297Sadrian 405220297Sadrian irq = rman_get_start(ires); 406220297Sadrian 407220297Sadrian if (irq >= NIRQS) 408220297Sadrian panic("%s: bad irq %d", __func__, irq); 409220297Sadrian 410220297Sadrian event = sc->sc_eventstab[irq]; 411220297Sadrian if (event == NULL) { 412220297Sadrian error = intr_event_create(&event, (void *)irq, 0, irq, 413220297Sadrian obio_mask_irq, obio_unmask_irq, 414220297Sadrian NULL, NULL, "obio intr%d:", irq); 415220297Sadrian 416220297Sadrian sc->sc_eventstab[irq] = event; 417220297Sadrian } 418220297Sadrian else 419220297Sadrian panic("obio: Can't share IRQs"); 420220297Sadrian 421220297Sadrian intr_event_add_handler(event, device_get_nameunit(child), filt, 422220297Sadrian handler, arg, intr_priority(flags), flags, cookiep); 423220297Sadrian 424220297Sadrian irqmask = 1 << irq; 425220297Sadrian priority = irq_priorities[irq]; 426220297Sadrian 427220297Sadrian if (priority == INTR_FIQ) 428220297Sadrian rt305x_ic_set(IC_INTTYPE, rt305x_ic_get(IC_INTTYPE) | irqmask); 429220297Sadrian else 430220297Sadrian rt305x_ic_set(IC_INTTYPE, rt305x_ic_get(IC_INTTYPE) & ~irqmask); 431220297Sadrian 432220297Sadrian /* enable */ 433220297Sadrian obio_unmask_irq((void*)irq); 434220297Sadrian 435220297Sadrian return (0); 436220297Sadrian} 437220297Sadrian 438220297Sadrianstatic int 439220297Sadrianobio_teardown_intr(device_t dev, device_t child, struct resource *ires, 440220297Sadrian void *cookie) 441220297Sadrian{ 442220297Sadrian struct obio_softc *sc = device_get_softc(dev); 443220297Sadrian int irq, result, priority; 444220297Sadrian uint32_t irqmask; 445220297Sadrian 446220297Sadrian irq = rman_get_start(ires); 447220297Sadrian if (irq >= NIRQS) 448220297Sadrian panic("%s: bad irq %d", __func__, irq); 449220297Sadrian 450220297Sadrian if (sc->sc_eventstab[irq] == NULL) 451220297Sadrian panic("Trying to teardown unoccupied IRQ"); 452220297Sadrian 453220297Sadrian irqmask = (1 << irq); 454220297Sadrian priority = irq_priorities[irq]; 455220297Sadrian 456220297Sadrian if (priority == INTR_FIQ) 457220297Sadrian rt305x_ic_set(IC_INTTYPE, rt305x_ic_get(IC_INTTYPE) & ~irqmask); 458220297Sadrian else 459220297Sadrian rt305x_ic_set(IC_INTTYPE, rt305x_ic_get(IC_INTTYPE) | irqmask); 460220297Sadrian 461220297Sadrian /* disable */ 462220297Sadrian obio_mask_irq((void*)irq); 463220297Sadrian 464220297Sadrian result = intr_event_remove_handler(cookie); 465220297Sadrian if (!result) { 466220297Sadrian sc->sc_eventstab[irq] = NULL; 467220297Sadrian } 468220297Sadrian 469220297Sadrian return (result); 470220297Sadrian} 471220297Sadrian 472220297Sadrianstatic int 473220297Sadrianobio_intr(void *arg) 474220297Sadrian{ 475220297Sadrian struct obio_softc *sc = arg; 476220297Sadrian struct intr_event *event; 477220297Sadrian uint32_t irqstat; 478220297Sadrian int irq; 479220297Sadrian 480220297Sadrian irqstat = rt305x_ic_get(IC_IRQ0STAT); 481220297Sadrian irqstat |= rt305x_ic_get(IC_IRQ1STAT); 482220297Sadrian 483220297Sadrian irq = 0; 484220297Sadrian while (irqstat != 0) { 485220297Sadrian if ((irqstat & 1) == 1) { 486220297Sadrian event = sc->sc_eventstab[irq]; 487220297Sadrian if (!event || TAILQ_EMPTY(&event->ie_handlers)) 488220297Sadrian continue; 489220297Sadrian 490220297Sadrian /* TODO: pass frame as an argument*/ 491220297Sadrian /* TODO: log stray interrupt */ 492220297Sadrian intr_event_handle(event, NULL); 493220297Sadrian } 494220297Sadrian irq++; 495220297Sadrian irqstat >>= 1; 496220297Sadrian } 497220297Sadrian 498220297Sadrian return (FILTER_HANDLED); 499220297Sadrian} 500220297Sadrian 501220297Sadrianstatic void 502220297Sadrianobio_add_res_child(device_t bus, const char *dname, int dunit, 503220297Sadrian long maddr, int msize, int irq) 504220297Sadrian{ 505220297Sadrian device_t child; 506220297Sadrian int result; 507220297Sadrian 508220297Sadrian child = BUS_ADD_CHILD(bus, 0, dname, dunit); 509220297Sadrian 510220297Sadrian result = bus_set_resource(child, SYS_RES_MEMORY, 0, 511220297Sadrian maddr, msize); 512220297Sadrian if (result != 0) 513220297Sadrian device_printf(bus, "warning: bus_set_resource() failed\n"); 514220297Sadrian 515220297Sadrian if (irq != -1) { 516220297Sadrian result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); 517220297Sadrian if (result != 0) 518220297Sadrian device_printf(bus, 519220297Sadrian "warning: bus_set_resource() failed\n"); 520220297Sadrian } 521220297Sadrian} 522220297Sadrian 523220297Sadrianstatic void 524220297Sadrianobio_hinted_child(device_t bus, const char *dname, int dunit) 525220297Sadrian{ 526220297Sadrian long maddr; 527220297Sadrian int msize; 528220297Sadrian int irq; 529220297Sadrian 530220297Sadrian /* 531220297Sadrian * Set hard-wired resources for hinted child using 532220297Sadrian * specific RIDs. 533220297Sadrian */ 534220297Sadrian resource_long_value(dname, dunit, "maddr", &maddr); 535220297Sadrian resource_int_value(dname, dunit, "msize", &msize); 536220297Sadrian 537220297Sadrian 538220297Sadrian if (resource_int_value(dname, dunit, "irq", &irq) == 0) irq = -1; 539220297Sadrian 540220297Sadrian obio_add_res_child(bus, dname, dunit, maddr, msize, irq); 541220297Sadrian} 542220297Sadrian 543220297Sadrianstatic device_t 544220297Sadrianobio_add_child(device_t bus, u_int order, const char *name, int unit) 545220297Sadrian{ 546220297Sadrian device_t child; 547220297Sadrian struct obio_ivar *ivar; 548220297Sadrian 549220297Sadrian ivar = malloc(sizeof(struct obio_ivar), M_DEVBUF, M_WAITOK | M_ZERO); 550220297Sadrian resource_list_init(&ivar->resources); 551220297Sadrian 552220297Sadrian child = device_add_child_ordered(bus, order, name, unit); 553220297Sadrian if (child == NULL) { 554220297Sadrian printf("Can't add child %s%d ordered\n", name, unit); 555220297Sadrian return (0); 556220297Sadrian } 557220297Sadrian 558220297Sadrian device_set_ivars(child, ivar); 559220297Sadrian 560220297Sadrian return (child); 561220297Sadrian} 562220297Sadrian 563220297Sadrian/* 564220297Sadrian * Helper routine for bus_generic_rl_get_resource/bus_generic_rl_set_resource 565220297Sadrian * Provides pointer to resource_list for these routines 566220297Sadrian */ 567220297Sadrianstatic struct resource_list * 568220297Sadrianobio_get_resource_list(device_t dev, device_t child) 569220297Sadrian{ 570220297Sadrian struct obio_ivar *ivar; 571220297Sadrian 572220297Sadrian ivar = device_get_ivars(child); 573220297Sadrian return (&(ivar->resources)); 574220297Sadrian} 575220297Sadrian 576220297Sadrianstatic int 577220297Sadrianobio_print_all_resources(device_t dev) 578220297Sadrian{ 579220297Sadrian struct obio_ivar *ivar = device_get_ivars(dev); 580220297Sadrian struct resource_list *rl = &ivar->resources; 581220297Sadrian int retval = 0; 582220297Sadrian 583220297Sadrian if (STAILQ_FIRST(rl)) 584220297Sadrian retval += printf(" at"); 585220297Sadrian 586297199Sjhibbits retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx"); 587297199Sjhibbits retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd"); 588220297Sadrian 589220297Sadrian return (retval); 590220297Sadrian} 591220297Sadrian 592220297Sadrianstatic int 593220297Sadrianobio_print_child(device_t bus, device_t child) 594220297Sadrian{ 595220297Sadrian int retval = 0; 596220297Sadrian 597220297Sadrian retval += bus_print_child_header(bus, child); 598220297Sadrian retval += obio_print_all_resources(child); 599220297Sadrian if (device_get_flags(child)) 600220297Sadrian retval += printf(" flags %#x", device_get_flags(child)); 601220297Sadrian retval += printf(" on %s\n", device_get_nameunit(bus)); 602220297Sadrian 603220297Sadrian return (retval); 604220297Sadrian} 605220297Sadrian 606220297Sadrianstatic device_method_t obio_methods[] = { 607220297Sadrian DEVMETHOD(bus_activate_resource, obio_activate_resource), 608220297Sadrian DEVMETHOD(bus_add_child, obio_add_child), 609220297Sadrian DEVMETHOD(bus_alloc_resource, obio_alloc_resource), 610220297Sadrian DEVMETHOD(bus_deactivate_resource, obio_deactivate_resource), 611220297Sadrian DEVMETHOD(bus_get_resource_list, obio_get_resource_list), 612220297Sadrian DEVMETHOD(bus_hinted_child, obio_hinted_child), 613220297Sadrian DEVMETHOD(bus_print_child, obio_print_child), 614220297Sadrian DEVMETHOD(bus_release_resource, obio_release_resource), 615220297Sadrian DEVMETHOD(bus_setup_intr, obio_setup_intr), 616220297Sadrian DEVMETHOD(bus_teardown_intr, obio_teardown_intr), 617220297Sadrian DEVMETHOD(device_attach, obio_attach), 618220297Sadrian DEVMETHOD(device_probe, obio_probe), 619220297Sadrian DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 620220297Sadrian DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), 621220297Sadrian 622220297Sadrian {0, 0}, 623220297Sadrian}; 624220297Sadrian 625220297Sadrianstatic driver_t obio_driver = { 626220297Sadrian "obio", 627220297Sadrian obio_methods, 628220297Sadrian sizeof(struct obio_softc), 629220297Sadrian}; 630220297Sadrianstatic devclass_t obio_devclass; 631220297Sadrian 632220297SadrianDRIVER_MODULE(obio, nexus, obio_driver, obio_devclass, 0, 0); 633