apb.c revision 298053
11558Srgrimes/*- 21558Srgrimes * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org> 31558Srgrimes * All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice unmodified, this list of conditions, and the following 101558Srgrimes * disclaimer. 111558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 121558Srgrimes * notice, this list of conditions and the following disclaimer in the 131558Srgrimes * documentation and/or other materials provided with the distribution. 141558Srgrimes * 151558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 161558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 171558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 181558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 191558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 201558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 211558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 221558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 231558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 241558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 251558Srgrimes * SUCH DAMAGE. 261558Srgrimes */ 271558Srgrimes 281558Srgrimes#include <sys/cdefs.h> 2950476Speter__FBSDID("$FreeBSD: head/sys/mips/atheros/apb.c 298053 2016-04-15 14:26:24Z pfg $"); 301558Srgrimes 31157535Sglebius#include <sys/param.h> 321558Srgrimes#include <sys/systm.h> 3379530Sru#include <sys/bus.h> 341558Srgrimes#include <sys/interrupt.h> 351558Srgrimes#include <sys/kernel.h> 361558Srgrimes#include <sys/module.h> 371558Srgrimes#include <sys/rman.h> 381558Srgrimes#include <sys/malloc.h> 391558Srgrimes#include <sys/pcpu.h> 4068960Sru#include <sys/proc.h> 41112985Smdodd#include <sys/pmc.h> 421558Srgrimes#include <sys/pmckern.h> 43149086Sglebius 44149086Sglebius#include <machine/bus.h> 45149086Sglebius#include <machine/intr_machdep.h> 461558Srgrimes 471558Srgrimes#include <mips/atheros/apbvar.h> 48112110Sru#include <mips/atheros/ar71xxreg.h> 4974029Sru#include <mips/atheros/ar71xx_setup.h> 50111287Sru 511558Srgrimes#define APB_INTR_PMC 5 52111287Sru 531558Srgrimes#undef APB_DEBUG 5456342Sbillf#ifdef APB_DEBUG 55157535Sglebius#define dprintf printf 56109731Smaxim#else 57112110Sru#define dprintf(x, arg...) 58112110Sru#endif /* APB_DEBUG */ 59112985Smdodd 60112110Sru#define DEVTOAPB(dev) ((struct apb_ivar *) device_get_ivars(dev)) 61112110Sru 62112110Srustatic int apb_activate_resource(device_t, device_t, int, int, 63112110Sru struct resource *); 64112110Srustatic device_t apb_add_child(device_t, u_int, const char *, int); 65112110Srustatic struct resource * 66112110Sru apb_alloc_resource(device_t, device_t, int, int *, rman_res_t, 67112110Sru rman_res_t, rman_res_t, u_int); 68112110Srustatic int apb_attach(device_t); 69112110Srustatic int apb_deactivate_resource(device_t, device_t, int, int, 7020540Sfenner struct resource *); 71112110Srustatic struct resource_list * 72157535Sglebius apb_get_resource_list(device_t, device_t); 73112110Srustatic void apb_hinted_child(device_t, const char *, int); 7423251Simpstatic int apb_filter(void *); 751558Srgrimesstatic int apb_probe(device_t); 7699501Scharnierstatic int apb_release_resource(device_t, device_t, int, int, 7799501Scharnier struct resource *); 7899501Scharnierstatic int apb_setup_intr(device_t, device_t, struct resource *, int, 791558Srgrimes driver_filter_t *, driver_intr_t *, void *, void **); 8023304Sjmgstatic int apb_teardown_intr(device_t, device_t, struct resource *, 811558Srgrimes void *); 821558Srgrimes 831558Srgrimesstatic void 841558Srgrimesapb_mask_irq(void *source) 851558Srgrimes{ 8623304Sjmg unsigned int irq = (unsigned int)source; 8723304Sjmg uint32_t reg; 8823304Sjmg 891558Srgrimes reg = ATH_READ_REG(AR71XX_MISC_INTR_MASK); 9023304Sjmg ATH_WRITE_REG(AR71XX_MISC_INTR_MASK, reg & ~(1 << irq)); 911558Srgrimes 9223304Sjmg} 9323304Sjmg 94111287Srustatic void 95111287Sruapb_unmask_irq(void *source) 9637671Scharnier{ 9777119Sphk uint32_t reg; 9877119Sphk unsigned int irq = (unsigned int)source; 9983940Siedowse 10081251Sru reg = ATH_READ_REG(AR71XX_MISC_INTR_MASK); 10181251Sru ATH_WRITE_REG(AR71XX_MISC_INTR_MASK, reg | (1 << irq)); 10283940Siedowse} 10377119Sphk 10483940Siedowsestatic int 10583940Siedowseapb_probe(device_t dev) 10683940Siedowse{ 10722417Sdanny 10857668Ssheldonh return (BUS_PROBE_NOWILDCARD); 10957668Ssheldonh} 11081251Sru 11181251Srustatic int 11257668Ssheldonhapb_attach(device_t dev) 11357668Ssheldonh{ 11423304Sjmg struct apb_softc *sc = device_get_softc(dev); 1151558Srgrimes int rid = 0; 11623304Sjmg 11781251Sru device_set_desc(dev, "APB Bus bridge"); 1181558Srgrimes 1191558Srgrimes sc->apb_mem_rman.rm_type = RMAN_ARRAY; 12041409Sbde sc->apb_mem_rman.rm_descr = "APB memory window"; 12141409Sbde 12241409Sbde if (rman_init(&sc->apb_mem_rman) != 0 || 12341409Sbde rman_manage_region(&sc->apb_mem_rman, 124149086Sglebius AR71XX_APB_BASE, 125149086Sglebius AR71XX_APB_BASE + AR71XX_APB_SIZE - 1) != 0) 126149086Sglebius panic("apb_attach: failed to set up memory rman"); 127149086Sglebius 128111287Sru sc->apb_irq_rman.rm_type = RMAN_ARRAY; 129111287Sru sc->apb_irq_rman.rm_descr = "APB IRQ"; 1301558Srgrimes 1311558Srgrimes if (rman_init(&sc->apb_irq_rman) != 0 || 1321558Srgrimes rman_manage_region(&sc->apb_irq_rman, 1331558Srgrimes APB_IRQ_BASE, APB_IRQ_END) != 0) 1341558Srgrimes panic("apb_attach: failed to set up IRQ rman"); 1351558Srgrimes 1361558Srgrimes if ((sc->sc_misc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 1371558Srgrimes RF_SHAREABLE | RF_ACTIVE)) == NULL) { 1381558Srgrimes device_printf(dev, "unable to allocate IRQ resource\n"); 1391558Srgrimes return (ENXIO); 14079754Sdd } 14170152Sru 14223304Sjmg if ((bus_setup_intr(dev, sc->sc_misc_irq, INTR_TYPE_MISC, 1431558Srgrimes apb_filter, NULL, sc, &sc->sc_misc_ih))) { 14441409Sbde device_printf(dev, 1451558Srgrimes "WARNING: unable to register interrupt handler\n"); 1461558Srgrimes return (ENXIO); 1471558Srgrimes } 1481558Srgrimes 1491558Srgrimes bus_generic_probe(dev); 150149086Sglebius bus_enumerate_hinted_children(dev); 151149086Sglebius bus_generic_attach(dev); 152149086Sglebius 153149086Sglebius /* 154152568Sru * Unmask performance counter IRQ 155149086Sglebius */ 156149086Sglebius apb_unmask_irq((void*)APB_INTR_PMC); 157149086Sglebius sc->sc_intr_counter[APB_INTR_PMC] = mips_intrcnt_create("apb irq5: pmc"); 158152568Sru 159149086Sglebius return (0); 160149086Sglebius} 161149086Sglebius 162149086Sglebiusstatic struct resource * 163149086Sglebiusapb_alloc_resource(device_t bus, device_t child, int type, int *rid, 164152568Sru rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 165152568Sru{ 166112110Sru struct apb_softc *sc = device_get_softc(bus); 167111287Sru struct apb_ivar *ivar = device_get_ivars(child); 168111287Sru struct resource *rv; 1691558Srgrimes struct resource_list_entry *rle; 1701558Srgrimes struct rman *rm; 1711558Srgrimes int isdefault, needactivate, passthrough; 1721558Srgrimes 1731558Srgrimes isdefault = (RMAN_IS_DEFAULT_RANGE(start, end)); 17441409Sbde needactivate = flags & RF_ACTIVE; 17541409Sbde /* 176108260Sru * Pass memory requests to nexus device 17741409Sbde */ 1781558Srgrimes passthrough = (device_get_parent(child) != bus); 1791558Srgrimes rle = NULL; 180111287Sru 181111287Sru dprintf("%s: entry (%p, %p, %d, %d, %p, %p, %jd, %d)\n", 18220540Sfenner __func__, bus, child, type, *rid, (void *)(intptr_t)start, 1831558Srgrimes (void *)(intptr_t)end, count, flags); 1841558Srgrimes 1851558Srgrimes if (passthrough) 1861558Srgrimes return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, 18737671Scharnier rid, start, end, count, flags)); 1881558Srgrimes 1891558Srgrimes /* 19023295Simp * If this is an allocation of the "default" range for a given RID, 191112110Sru * and we know what the resources for this device are (ie. they aren't 192112110Sru * maintained by a child bus), then work out the start/end values. 193112110Sru */ 194112110Sru 195112110Sru if (isdefault) { 196112110Sru rle = resource_list_find(&ivar->resources, type, *rid); 197112110Sru if (rle == NULL) { 198112110Sru return (NULL); 199112110Sru } 200112110Sru 201112110Sru if (rle->res != NULL) { 202111765Smdodd panic("%s: resource entry is busy", __func__); 203112110Sru } 204112110Sru start = rle->start; 205111765Smdodd end = rle->end; 206112110Sru count = rle->count; 207111930Smdodd 208111927Smdodd dprintf("%s: default resource (%p, %p, %ld)\n", 209111927Smdodd __func__, (void *)(intptr_t)start, 210111927Smdodd (void *)(intptr_t)end, count); 211111927Smdodd } 212111927Smdodd 2131558Srgrimes switch (type) { 2141558Srgrimes case SYS_RES_IRQ: 2151558Srgrimes rm = &sc->apb_irq_rman; 216104339Sdd break; 217104339Sdd case SYS_RES_MEMORY: 218111287Sru rm = &sc->apb_mem_rman; 219111287Sru break; 220111287Sru default: 221111287Sru printf("%s: unknown resource type %d\n", __func__, type); 222111287Sru return (0); 223111287Sru } 224111287Sru 2251558Srgrimes rv = rman_reserve_resource(rm, start, end, count, flags, child); 22623304Sjmg if (rv == NULL) { 22723304Sjmg printf("%s: could not reserve resource\n", __func__); 22823304Sjmg return (0); 2291558Srgrimes } 2301558Srgrimes 2311558Srgrimes rman_set_rid(rv, *rid); 2321558Srgrimes 2331558Srgrimes if (needactivate) { 23417724Sfenner if (bus_activate_resource(child, type, *rid, rv)) { 23517724Sfenner printf("%s: could not activate resource\n", __func__); 23623304Sjmg rman_release_resource(rv); 23723304Sjmg return (0); 23817724Sfenner } 23917724Sfenner } 24017724Sfenner 24117724Sfenner return (rv); 242111287Sru} 243111287Sru 244111287Srustatic int 24517724Sfennerapb_activate_resource(device_t bus, device_t child, int type, int rid, 24679754Sdd struct resource *r) 24717724Sfenner{ 24817724Sfenner 24917724Sfenner /* XXX: should we mask/unmask IRQ here? */ 2501558Srgrimes return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child, 2511558Srgrimes type, rid, r)); 2521558Srgrimes} 2531558Srgrimes 2541558Srgrimesstatic int 2551558Srgrimesapb_deactivate_resource(device_t bus, device_t child, int type, int rid, 2561558Srgrimes struct resource *r) 2571558Srgrimes{ 2581558Srgrimes 2591558Srgrimes /* XXX: should we mask/unmask IRQ here? */ 2601558Srgrimes return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child, 2611558Srgrimes type, rid, r)); 26223247Swollman} 26323247Swollman 26423247Swollmanstatic int 26523247Swollmanapb_release_resource(device_t dev, device_t child, int type, 26623247Swollman int rid, struct resource *r) 26734976Simp{ 26834976Simp struct resource_list *rl; 26934976Simp struct resource_list_entry *rle; 27023247Swollman 27123247Swollman rl = apb_get_resource_list(dev, child); 27223247Swollman if (rl == NULL) 2731558Srgrimes return (EINVAL); 2741558Srgrimes rle = resource_list_find(rl, type, rid); 2751558Srgrimes if (rle == NULL) 2761558Srgrimes return (EINVAL); 2771558Srgrimes rman_release_resource(r); 27879754Sdd rle->res = NULL; 27981251Sru 28081251Sru return (0); 281111287Sru} 282111287Sru 283111287Srustatic int 284111287Sruapb_setup_intr(device_t bus, device_t child, struct resource *ires, 285111287Sru int flags, driver_filter_t *filt, driver_intr_t *handler, 286111287Sru void *arg, void **cookiep) 287111287Sru{ 288111287Sru struct apb_softc *sc = device_get_softc(bus); 2891558Srgrimes struct intr_event *event; 29079754Sdd int irq, error; 2911558Srgrimes 2921558Srgrimes irq = rman_get_start(ires); 2931558Srgrimes 2941558Srgrimes if (irq > APB_IRQ_END) 2951558Srgrimes panic("%s: bad irq %d", __func__, irq); 29641409Sbde 297109734Smaxim event = sc->sc_eventstab[irq]; 298149086Sglebius if (event == NULL) { 299111287Sru error = intr_event_create(&event, (void *)irq, 0, irq, 300111287Sru apb_mask_irq, apb_unmask_irq, 301111287Sru NULL, NULL, 30255996Sbillf "apb intr%d:", irq); 30355996Sbillf 304108317Sschweikh if (error == 0) { 3051558Srgrimes sc->sc_eventstab[irq] = event; 3061558Srgrimes sc->sc_intr_counter[irq] = 3071558Srgrimes mips_intrcnt_create(event->ie_name); 3081558Srgrimes } 3091558Srgrimes else 3101558Srgrimes return (error); 311157535Sglebius } 312157535Sglebius 313157535Sglebius intr_event_add_handler(event, device_get_nameunit(child), filt, 314157535Sglebius handler, arg, intr_priority(flags), flags, cookiep); 315109731Smaxim mips_intrcnt_setname(sc->sc_intr_counter[irq], event->ie_fullname); 316109731Smaxim 3171558Srgrimes apb_unmask_irq((void*)irq); 3181558Srgrimes 3191558Srgrimes return (0); 32023304Sjmg} 3211558Srgrimes 3221558Srgrimesstatic int 32379754Sddapb_teardown_intr(device_t dev, device_t child, struct resource *ires, 32423304Sjmg void *cookie) 3251558Srgrimes{ 3261558Srgrimes struct apb_softc *sc = device_get_softc(dev); 3271558Srgrimes int irq, result; 32827508Swollman 32923304Sjmg irq = rman_get_start(ires); 33081251Sru if (irq > APB_IRQ_END) 33123304Sjmg panic("%s: bad irq %d", __func__, irq); 3321558Srgrimes 33327508Swollman if (sc->sc_eventstab[irq] == NULL) 33490351Smaxim panic("Trying to teardown unoccupied IRQ"); 33527508Swollman 3361558Srgrimes apb_mask_irq((void*)irq); 33790351Smaxim 33890351Smaxim result = intr_event_remove_handler(cookie); 33990351Smaxim if (!result) 34090351Smaxim sc->sc_eventstab[irq] = NULL; 34190351Smaxim 34290351Smaxim return (result); 34390351Smaxim} 34490351Smaxim 34590351Smaximstatic int 34690351Smaximapb_filter(void *arg) 34790351Smaxim{ 34890351Smaxim struct apb_softc *sc = arg; 3491558Srgrimes struct intr_event *event; 3501558Srgrimes uint32_t reg, irq; 3511558Srgrimes struct thread *td; 35223304Sjmg struct trapframe *tf; 3531558Srgrimes 3541558Srgrimes reg = ATH_READ_REG(AR71XX_MISC_INTR_STATUS); 3551558Srgrimes for (irq = 0; irq < APB_NIRQS; irq++) { 3561558Srgrimes if (reg & (1 << irq)) { 3571558Srgrimes 3581558Srgrimes switch (ar71xx_soc) { 35923304Sjmg case AR71XX_SOC_AR7240: 3601558Srgrimes case AR71XX_SOC_AR7241: 3611558Srgrimes case AR71XX_SOC_AR7242: 3621558Srgrimes case AR71XX_SOC_AR9330: 3631558Srgrimes case AR71XX_SOC_AR9331: 36423304Sjmg case AR71XX_SOC_AR9341: 36581251Sru case AR71XX_SOC_AR9342: 3661558Srgrimes case AR71XX_SOC_AR9344: 3671558Srgrimes case AR71XX_SOC_QCA9533: 3681558Srgrimes case AR71XX_SOC_QCA9533_V2: 3691558Srgrimes case AR71XX_SOC_QCA9556: 37081251Sru case AR71XX_SOC_QCA9558: 37181251Sru /* ACK/clear the given interrupt */ 37281251Sru ATH_WRITE_REG(AR71XX_MISC_INTR_STATUS, 3731558Srgrimes (1 << irq)); 3741558Srgrimes break; 37523304Sjmg default: 3761558Srgrimes /* fallthrough */ 3771558Srgrimes break; 3781558Srgrimes } 3791558Srgrimes 3801558Srgrimes event = sc->sc_eventstab[irq]; 38199501Scharnier /* always count interrupts; spurious or otherwise */ 38299501Scharnier mips_intrcnt_inc(sc->sc_intr_counter[irq]); 38399501Scharnier if (!event || TAILQ_EMPTY(&event->ie_handlers)) { 38420540Sfenner if (irq == APB_INTR_PMC) { 38520540Sfenner td = PCPU_GET(curthread); 3861558Srgrimes tf = td->td_intr_frame; 38723304Sjmg 38881251Sru if (pmc_intr) 38923304Sjmg (*pmc_intr)(PCPU_GET(cpuid), tf); 3901558Srgrimes continue; 39120540Sfenner } 39220540Sfenner /* Ignore timer interrupts */ 39320540Sfenner if (irq != 0 && irq != 8 && irq != 9 && irq != 10) 3941558Srgrimes printf("Stray APB IRQ %d\n", irq); 3951558Srgrimes continue; 3961558Srgrimes } 39737671Scharnier 39827508Swollman intr_event_handle(event, PCPU_GET(curthread)->td_intr_frame); 3991558Srgrimes } 40023304Sjmg } 40127508Swollman 40223304Sjmg return (FILTER_HANDLED); 40323304Sjmg} 4041558Srgrimes 4051558Srgrimesstatic void 4061558Srgrimesapb_hinted_child(device_t bus, const char *dname, int dunit) 40727508Swollman{ 40823304Sjmg device_t child; 40923304Sjmg long maddr; 41023304Sjmg int msize; 41127508Swollman int irq; 41227508Swollman int result; 41323304Sjmg int mem_hints_count; 4141558Srgrimes 4151558Srgrimes child = BUS_ADD_CHILD(bus, 0, dname, dunit); 4161558Srgrimes 4171558Srgrimes /* 4181558Srgrimes * Set hard-wired resources for hinted child using 41923304Sjmg * specific RIDs. 42027508Swollman */ 42123304Sjmg mem_hints_count = 0; 42223304Sjmg if (resource_long_value(dname, dunit, "maddr", &maddr) == 0) 4231558Srgrimes mem_hints_count++; 4241558Srgrimes if (resource_int_value(dname, dunit, "msize", &msize) == 0) 4251558Srgrimes mem_hints_count++; 4261558Srgrimes 42768960Sru /* check if all info for mem resource has been provided */ 4281558Srgrimes if ((mem_hints_count > 0) && (mem_hints_count < 2)) { 4291558Srgrimes printf("Either maddr or msize hint is missing for %s%d\n", 4301558Srgrimes dname, dunit); 4311558Srgrimes } else if (mem_hints_count) { 4321558Srgrimes result = bus_set_resource(child, SYS_RES_MEMORY, 0, 4331558Srgrimes maddr, msize); 4341558Srgrimes if (result != 0) 4351558Srgrimes device_printf(bus, 4361558Srgrimes "warning: bus_set_resource() failed\n"); 4371558Srgrimes } 4381558Srgrimes 4391558Srgrimes if (resource_int_value(dname, dunit, "irq", &irq) == 0) { 440116806Sru result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); 4411558Srgrimes if (result != 0) 4421558Srgrimes device_printf(bus, 443116806Sru "warning: bus_set_resource() failed\n"); 444116806Sru } 44581251Sru} 44627508Swollman 44727508Swollmanstatic device_t 44881251Sruapb_add_child(device_t bus, u_int order, const char *name, int unit) 4491558Srgrimes{ 45037671Scharnier device_t child; 45137671Scharnier struct apb_ivar *ivar; 45237671Scharnier 4531558Srgrimes ivar = malloc(sizeof(struct apb_ivar), M_DEVBUF, M_WAITOK | M_ZERO); 4541558Srgrimes if (ivar == NULL) { 4551558Srgrimes printf("Failed to allocate ivar\n"); 4561558Srgrimes return (0); 4571558Srgrimes } 45879754Sdd resource_list_init(&ivar->resources); 45923304Sjmg 46023304Sjmg child = device_add_child_ordered(bus, order, name, unit); 4611558Srgrimes if (child == NULL) { 4621558Srgrimes printf("Can't add child %s%d ordered\n", name, unit); 4631558Srgrimes return (0); 4641558Srgrimes } 46537671Scharnier 46637671Scharnier device_set_ivars(child, ivar); 46737671Scharnier 4681558Srgrimes return (child); 4691558Srgrimes} 4701558Srgrimes 4711558Srgrimes/* 4721558Srgrimes * Helper routine for bus_generic_rl_get_resource/bus_generic_rl_set_resource 4731558Srgrimes * Provides pointer to resource_list for these routines 47437671Scharnier */ 47537671Scharnierstatic struct resource_list * 47637671Scharnierapb_get_resource_list(device_t dev, device_t child) 4771558Srgrimes{ 4781558Srgrimes struct apb_ivar *ivar; 4791558Srgrimes 4801558Srgrimes ivar = device_get_ivars(child); 4811558Srgrimes return (&(ivar->resources)); 4821558Srgrimes} 4831558Srgrimes 48479754Sddstatic int 48537671Scharnierapb_print_all_resources(device_t dev) 48627508Swollman{ 4871558Srgrimes struct apb_ivar *ndev = DEVTOAPB(dev); 4881558Srgrimes struct resource_list *rl = &ndev->resources; 4891558Srgrimes int retval = 0; 4901558Srgrimes 49123304Sjmg if (STAILQ_FIRST(rl)) 4921558Srgrimes retval += printf(" at"); 4931558Srgrimes 4941558Srgrimes retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx"); 49523304Sjmg retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd"); 4961558Srgrimes 4971558Srgrimes return (retval); 4981558Srgrimes} 4991558Srgrimes 5001558Srgrimesstatic int 5011558Srgrimesapb_print_child(device_t bus, device_t child) 5021558Srgrimes{ 5031558Srgrimes int retval = 0; 5041558Srgrimes 5051558Srgrimes retval += bus_print_child_header(bus, child); 506186843Sdanger retval += apb_print_all_resources(child); 50723247Swollman if (device_get_flags(child)) 50823304Sjmg retval += printf(" flags %#x", device_get_flags(child)); 509187067Sdanger retval += printf(" on %s\n", device_get_nameunit(bus)); 510187067Sdanger 511187067Sdanger return (retval); 512187067Sdanger} 513187067Sdanger 514187067Sdanger 515187067Sdangerstatic device_method_t apb_methods[] = { 516187067Sdanger DEVMETHOD(bus_activate_resource, apb_activate_resource), 517187067Sdanger DEVMETHOD(bus_add_child, apb_add_child), 518187067Sdanger DEVMETHOD(bus_alloc_resource, apb_alloc_resource), 519187067Sdanger DEVMETHOD(bus_deactivate_resource, apb_deactivate_resource), 520187067Sdanger DEVMETHOD(bus_get_resource_list, apb_get_resource_list), 52123247Swollman DEVMETHOD(bus_hinted_child, apb_hinted_child), 52223247Swollman DEVMETHOD(bus_release_resource, apb_release_resource), 52323247Swollman DEVMETHOD(bus_setup_intr, apb_setup_intr), 52423247Swollman DEVMETHOD(bus_teardown_intr, apb_teardown_intr), 52523247Swollman DEVMETHOD(device_attach, apb_attach), 52623247Swollman DEVMETHOD(device_probe, apb_probe), 52723247Swollman DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 52823247Swollman DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), 52999501Scharnier DEVMETHOD(bus_print_child, apb_print_child), 53023247Swollman 53123247Swollman DEVMETHOD_END 53223247Swollman}; 53323247Swollman 53499501Scharnierstatic driver_t apb_driver = { 53534673Scharnier "apb", 53634673Scharnier apb_methods, 53723247Swollman sizeof(struct apb_softc), 5381558Srgrimes}; 5391558Srgrimesstatic devclass_t apb_devclass; 5401558Srgrimes 5411558SrgrimesDRIVER_MODULE(apb, nexus, apb_driver, apb_devclass, 0, 0); 5421558Srgrimes