fhc.c revision 190098
1111072Sjake/*- 2111072Sjake * Copyright (c) 2003 Jake Burkholder. 3167308Smarius * Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org> 4111072Sjake * All rights reserved. 5111072Sjake * 6111072Sjake * Redistribution and use in source and binary forms, with or without 7111072Sjake * modification, are permitted provided that the following conditions 8111072Sjake * are met: 9111072Sjake * 1. Redistributions of source code must retain the above copyright 10111072Sjake * notice, this list of conditions and the following disclaimer. 11111072Sjake * 2. Redistributions in binary form must reproduce the above copyright 12111072Sjake * notice, this list of conditions and the following disclaimer in the 13111072Sjake * documentation and/or other materials provided with the distribution. 14111072Sjake * 15111072Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16111072Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17111072Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18111072Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19111072Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20111072Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21111072Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22111072Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23111072Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24111072Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25111072Sjake * SUCH DAMAGE. 26111072Sjake */ 27111072Sjake 28143129Smarius#include <sys/cdefs.h> 29143129Smarius__FBSDID("$FreeBSD: head/sys/sparc64/fhc/fhc.c 190098 2009-03-19 20:29:23Z marius $"); 30143129Smarius 31111072Sjake#include <sys/param.h> 32111072Sjake#include <sys/systm.h> 33111072Sjake#include <sys/bus.h> 34111072Sjake#include <sys/kernel.h> 35111072Sjake#include <sys/malloc.h> 36167308Smarius#include <sys/module.h> 37111123Sjake#include <sys/pcpu.h> 38111072Sjake 39143826Smarius#include <dev/led/led.h> 40133589Smarius#include <dev/ofw/ofw_bus.h> 41152684Smarius#include <dev/ofw/ofw_bus_subr.h> 42111072Sjake#include <dev/ofw/openfirm.h> 43111072Sjake 44111072Sjake#include <machine/bus.h> 45111072Sjake#include <machine/bus_common.h> 46111072Sjake#include <machine/resource.h> 47111072Sjake 48111072Sjake#include <sys/rman.h> 49111072Sjake 50111072Sjake#include <sparc64/fhc/fhcreg.h> 51111072Sjake#include <sparc64/sbus/ofw_sbus.h> 52111072Sjake 53111072Sjakestruct fhc_devinfo { 54152684Smarius struct ofw_bus_devinfo fdi_obdinfo; 55111072Sjake struct resource_list fdi_rl; 56111072Sjake}; 57111072Sjake 58167308Smariusstruct fhc_softc { 59172066Smarius struct resource *sc_memres[FHC_NREG]; 60167308Smarius int sc_nrange; 61167308Smarius struct sbus_ranges *sc_ranges; 62167308Smarius int sc_ign; 63167308Smarius struct cdev *sc_led_dev; 64167308Smarius}; 65167308Smarius 66167308Smariusstatic device_probe_t fhc_probe; 67167308Smariusstatic device_attach_t fhc_attach; 68167308Smariusstatic bus_print_child_t fhc_print_child; 69167308Smariusstatic bus_probe_nomatch_t fhc_probe_nomatch; 70167308Smariusstatic bus_setup_intr_t fhc_setup_intr; 71167308Smariusstatic bus_alloc_resource_t fhc_alloc_resource; 72167308Smariusstatic bus_get_resource_list_t fhc_get_resource_list; 73167308Smariusstatic ofw_bus_get_devinfo_t fhc_get_devinfo; 74167308Smarius 75172066Smariusstatic void fhc_intr_enable(void *); 76172066Smariusstatic void fhc_intr_disable(void *); 77178443Smariusstatic void fhc_intr_assign(void *); 78178443Smariusstatic void fhc_intr_clear(void *); 79143826Smariusstatic void fhc_led_func(void *, int); 80152684Smariusstatic int fhc_print_res(struct fhc_devinfo *); 81111123Sjake 82167308Smariusstatic device_method_t fhc_methods[] = { 83167308Smarius /* Device interface */ 84167308Smarius DEVMETHOD(device_probe, fhc_probe), 85167308Smarius DEVMETHOD(device_attach, fhc_attach), 86167308Smarius DEVMETHOD(device_shutdown, bus_generic_shutdown), 87167308Smarius DEVMETHOD(device_suspend, bus_generic_suspend), 88167308Smarius DEVMETHOD(device_resume, bus_generic_resume), 89167308Smarius 90167308Smarius /* Bus interface */ 91167308Smarius DEVMETHOD(bus_print_child, fhc_print_child), 92167308Smarius DEVMETHOD(bus_probe_nomatch, fhc_probe_nomatch), 93167308Smarius DEVMETHOD(bus_alloc_resource, fhc_alloc_resource), 94167308Smarius DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 95167308Smarius DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 96190098Smarius DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), 97190098Smarius DEVMETHOD(bus_setup_intr, fhc_setup_intr), 98190098Smarius DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 99190098Smarius DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 100167308Smarius DEVMETHOD(bus_get_resource_list, fhc_get_resource_list), 101167308Smarius 102167308Smarius /* ofw_bus interface */ 103167308Smarius DEVMETHOD(ofw_bus_get_devinfo, fhc_get_devinfo), 104167308Smarius DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 105167308Smarius DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 106167308Smarius DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 107167308Smarius DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 108167308Smarius DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 109167308Smarius 110190098Smarius KOBJMETHOD_END 111167308Smarius}; 112167308Smarius 113167308Smariusstatic driver_t fhc_driver = { 114167308Smarius "fhc", 115167308Smarius fhc_methods, 116167308Smarius sizeof(struct fhc_softc), 117167308Smarius}; 118167308Smarius 119167308Smariusstatic devclass_t fhc_devclass; 120167308Smarius 121167308SmariusDRIVER_MODULE(fhc, central, fhc_driver, fhc_devclass, 0, 0); 122167308SmariusDRIVER_MODULE(fhc, nexus, fhc_driver, fhc_devclass, 0, 0); 123182070SmariusMODULE_DEPEND(fhc, central, 1, 1, 1); 124182070SmariusMODULE_VERSION(fhc, 1); 125167308Smarius 126172066Smariusstatic const struct intr_controller fhc_ic = { 127172066Smarius fhc_intr_enable, 128172066Smarius fhc_intr_disable, 129178443Smarius fhc_intr_assign, 130178443Smarius fhc_intr_clear 131172066Smarius}; 132172066Smarius 133172066Smariusstruct fhc_icarg { 134172066Smarius struct fhc_softc *fica_sc; 135172066Smarius struct resource *fica_memres; 136172066Smarius}; 137172066Smarius 138167308Smariusstatic int 139111072Sjakefhc_probe(device_t dev) 140111072Sjake{ 141111072Sjake 142167308Smarius if (strcmp(ofw_bus_get_name(dev), "fhc") == 0) { 143167308Smarius device_set_desc(dev, "fhc"); 144167308Smarius return (0); 145167308Smarius } 146167308Smarius return (ENXIO); 147111072Sjake} 148111072Sjake 149167308Smariusstatic int 150111072Sjakefhc_attach(device_t dev) 151111072Sjake{ 152143826Smarius char ledname[sizeof("boardXX")]; 153111072Sjake struct fhc_devinfo *fdi; 154172066Smarius struct fhc_icarg *fica; 155172066Smarius struct fhc_softc *sc; 156111072Sjake struct sbus_regs *reg; 157111072Sjake phandle_t child; 158111072Sjake phandle_t node; 159111072Sjake device_t cdev; 160167308Smarius uint32_t board; 161111123Sjake uint32_t ctrl; 162143142Smarius uint32_t *intr; 163143142Smarius uint32_t iv; 164111072Sjake char *name; 165172066Smarius int central; 166167308Smarius int error; 167167308Smarius int i; 168190098Smarius int j; 169111072Sjake 170111072Sjake sc = device_get_softc(dev); 171167308Smarius node = ofw_bus_get_node(dev); 172111072Sjake 173172066Smarius central = 0; 174167308Smarius if (strcmp(device_get_name(device_get_parent(dev)), "central") == 0) 175172066Smarius central = 1; 176167308Smarius 177167308Smarius for (i = 0; i < FHC_NREG; i++) { 178190098Smarius j = i; 179167308Smarius sc->sc_memres[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 180190098Smarius &j, RF_ACTIVE); 181167308Smarius if (sc->sc_memres[i] == NULL) { 182167308Smarius device_printf(dev, "cannot allocate resource %d\n", i); 183167308Smarius error = ENXIO; 184167308Smarius goto fail_memres; 185167308Smarius } 186167308Smarius } 187167308Smarius 188172066Smarius if (central != 0) { 189172066Smarius board = bus_read_4(sc->sc_memres[FHC_INTERNAL], FHC_BSR); 190172066Smarius board = ((board >> 16) & 0x1) | ((board >> 12) & 0xe); 191167308Smarius } else { 192172066Smarius if (OF_getprop(node, "board#", &board, sizeof(board)) == -1) { 193167308Smarius device_printf(dev, "cannot get board number\n"); 194167308Smarius error = ENXIO; 195167308Smarius goto fail_memres; 196167308Smarius } 197167308Smarius } 198167308Smarius 199172066Smarius device_printf(dev, "board %d, ", board); 200143129Smarius if (OF_getprop_alloc(node, "board-model", 1, (void **)&name) != -1) { 201143826Smarius printf("model %s\n", name); 202143129Smarius free(name, M_OFWPROP); 203143826Smarius } else 204143826Smarius printf("model unknown\n"); 205143129Smarius 206111072Sjake for (i = FHC_FANFAIL; i <= FHC_TOD; i++) { 207172066Smarius bus_write_4(sc->sc_memres[i], FHC_ICLR, 0x0); 208172066Smarius (void)bus_read_4(sc->sc_memres[i], FHC_ICLR); 209111072Sjake } 210111072Sjake 211172066Smarius sc->sc_ign = board << 1; 212172066Smarius bus_write_4(sc->sc_memres[FHC_IGN], 0x0, sc->sc_ign); 213172066Smarius sc->sc_ign = bus_read_4(sc->sc_memres[FHC_IGN], 0x0); 214111123Sjake 215172066Smarius ctrl = bus_read_4(sc->sc_memres[FHC_INTERNAL], FHC_CTRL); 216172066Smarius if (central == 0) 217111123Sjake ctrl |= FHC_CTRL_IXIST; 218111123Sjake ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE); 219172066Smarius bus_write_4(sc->sc_memres[FHC_INTERNAL], FHC_CTRL, ctrl); 220172066Smarius (void)bus_read_4(sc->sc_memres[FHC_INTERNAL], FHC_CTRL); 221111123Sjake 222111072Sjake sc->sc_nrange = OF_getprop_alloc(node, "ranges", 223111072Sjake sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges); 224111072Sjake if (sc->sc_nrange == -1) { 225167308Smarius device_printf(dev, "cannot get ranges\n"); 226167308Smarius error = ENXIO; 227167308Smarius goto fail_memres; 228111072Sjake } 229111072Sjake 230172066Smarius /* 231172066Smarius * Apparently only the interrupt controller of boards hanging off 232172066Smarius * of central(4) is indented to be used, otherwise we would have 233172066Smarius * conflicts registering the interrupt controllers for all FHC 234172066Smarius * boards as the board number and thus the IGN isn't unique. 235172066Smarius */ 236172066Smarius if (central == 1) { 237172066Smarius /* 238172066Smarius * Hunt through all the interrupt mapping regs and register 239172066Smarius * our interrupt controller for the corresponding interrupt 240190098Smarius * vectors. We do this early in order to be able to catch 241190098Smarius * stray interrupts. 242172066Smarius */ 243172066Smarius for (i = FHC_FANFAIL; i <= FHC_TOD; i++) { 244172066Smarius fica = malloc(sizeof(*fica), M_DEVBUF, M_NOWAIT); 245172066Smarius if (fica == NULL) 246172066Smarius panic("%s: could not allocate interrupt " 247172066Smarius "controller argument", __func__); 248172066Smarius fica->fica_sc = sc; 249172066Smarius fica->fica_memres = sc->sc_memres[i]; 250172066Smarius#ifdef FHC_DEBUG 251172066Smarius device_printf(dev, "intr map %d: %#lx, clr: %#lx\n", i, 252172066Smarius (u_long)bus_read_4(fica->fica_memres, FHC_IMAP), 253172066Smarius (u_long)bus_read_4(fica->fica_memres, FHC_ICLR)); 254172066Smarius#endif 255172066Smarius /* 256172066Smarius * XXX we only pick the INO rather than the INR 257172066Smarius * from the IMR since the firmware may not provide 258172066Smarius * the IGN and the IGN is constant for all devices 259172066Smarius * on that FireHose controller. 260172066Smarius */ 261190098Smarius j = intr_controller_register(INTMAP_VEC(sc->sc_ign, 262172066Smarius INTINO(bus_read_4(fica->fica_memres, FHC_IMAP))), 263190098Smarius &fhc_ic, fica); 264190098Smarius if (j != 0) 265190098Smarius device_printf(dev, "could not register " 266190098Smarius "interrupt controller for map %d (%d)\n", 267190098Smarius i, j); 268172066Smarius } 269172066Smarius } else { 270172066Smarius snprintf(ledname, sizeof(ledname), "board%d", board); 271143826Smarius sc->sc_led_dev = led_create(fhc_led_func, sc, ledname); 272143826Smarius } 273143826Smarius 274111072Sjake for (child = OF_child(node); child != 0; child = OF_peer(child)) { 275152684Smarius fdi = malloc(sizeof(*fdi), M_DEVBUF, M_WAITOK | M_ZERO); 276152684Smarius if (ofw_bus_gen_setup_devinfo(&fdi->fdi_obdinfo, child) != 0) { 277152684Smarius free(fdi, M_DEVBUF); 278111072Sjake continue; 279152684Smarius } 280190098Smarius i = OF_getprop_alloc(child, "reg", sizeof(*reg), 281152684Smarius (void **)®); 282190098Smarius if (i == -1) { 283152684Smarius device_printf(dev, "<%s>: incomplete\n", 284152684Smarius fdi->fdi_obdinfo.obd_name); 285152684Smarius ofw_bus_gen_destroy_devinfo(&fdi->fdi_obdinfo); 286152684Smarius free(fdi, M_DEVBUF); 287152684Smarius continue; 288152684Smarius } 289152684Smarius resource_list_init(&fdi->fdi_rl); 290190098Smarius for (j = 0; j < i; j++) 291190098Smarius resource_list_add(&fdi->fdi_rl, SYS_RES_MEMORY, j, 292190098Smarius reg[j].sbr_offset, reg[j].sbr_offset + 293190098Smarius reg[j].sbr_size, reg[j].sbr_size); 294152684Smarius free(reg, M_OFWPROP); 295172066Smarius if (central == 1) { 296190098Smarius i = OF_getprop_alloc(child, "interrupts", 297172066Smarius sizeof(*intr), (void **)&intr); 298190098Smarius if (i != -1) { 299190098Smarius for (j = 0; j < i; j++) { 300190098Smarius iv = INTMAP_VEC(sc->sc_ign, intr[j]); 301172066Smarius resource_list_add(&fdi->fdi_rl, 302190098Smarius SYS_RES_IRQ, j, iv, iv, 1); 303172066Smarius } 304172066Smarius free(intr, M_OFWPROP); 305152684Smarius } 306152684Smarius } 307111072Sjake cdev = device_add_child(dev, NULL, -1); 308152684Smarius if (cdev == NULL) { 309152684Smarius device_printf(dev, "<%s>: device_add_child failed\n", 310152684Smarius fdi->fdi_obdinfo.obd_name); 311152684Smarius resource_list_free(&fdi->fdi_rl); 312152684Smarius ofw_bus_gen_destroy_devinfo(&fdi->fdi_obdinfo); 313152684Smarius free(fdi, M_DEVBUF); 314152684Smarius continue; 315152684Smarius } 316152684Smarius device_set_ivars(cdev, fdi); 317111072Sjake } 318111072Sjake 319111072Sjake return (bus_generic_attach(dev)); 320167308Smarius 321167308Smarius fail_memres: 322167308Smarius for (i = 0; i < FHC_NREG; i++) 323167308Smarius if (sc->sc_memres[i] != NULL) 324167308Smarius bus_release_resource(dev, SYS_RES_MEMORY, 325167308Smarius rman_get_rid(sc->sc_memres[i]), sc->sc_memres[i]); 326182070Smarius return (error); 327111072Sjake} 328111072Sjake 329167308Smariusstatic int 330111072Sjakefhc_print_child(device_t dev, device_t child) 331111072Sjake{ 332111072Sjake int rv; 333111072Sjake 334111072Sjake rv = bus_print_child_header(dev, child); 335152684Smarius rv += fhc_print_res(device_get_ivars(child)); 336111072Sjake rv += bus_print_child_footer(dev, child); 337111072Sjake return (rv); 338111072Sjake} 339111072Sjake 340167308Smariusstatic void 341111072Sjakefhc_probe_nomatch(device_t dev, device_t child) 342111072Sjake{ 343152684Smarius const char *type; 344111072Sjake 345152684Smarius device_printf(dev, "<%s>", ofw_bus_get_name(child)); 346152684Smarius fhc_print_res(device_get_ivars(child)); 347152684Smarius type = ofw_bus_get_type(child); 348111072Sjake printf(" type %s (no driver attached)\n", 349152684Smarius type != NULL ? type : "unknown"); 350111072Sjake} 351111072Sjake 352172066Smariusstatic void 353172066Smariusfhc_intr_enable(void *arg) 354111072Sjake{ 355172066Smarius struct intr_vector *iv = arg; 356172066Smarius struct fhc_icarg *fica = iv->iv_icarg; 357111072Sjake 358172066Smarius bus_write_4(fica->fica_memres, FHC_IMAP, 359172066Smarius INTMAP_ENABLE(iv->iv_vec, iv->iv_mid)); 360172066Smarius (void)bus_read_4(fica->fica_memres, FHC_IMAP); 361111072Sjake} 362111072Sjake 363172066Smariusstatic void 364172066Smariusfhc_intr_disable(void *arg) 365111072Sjake{ 366172066Smarius struct intr_vector *iv = arg; 367172066Smarius struct fhc_icarg *fica = iv->iv_icarg; 368111072Sjake 369172066Smarius bus_write_4(fica->fica_memres, FHC_IMAP, iv->iv_vec); 370172066Smarius (void)bus_read_4(fica->fica_memres, FHC_IMAP); 371111072Sjake} 372111072Sjake 373172066Smariusstatic void 374178443Smariusfhc_intr_assign(void *arg) 375170387Spiso{ 376172066Smarius struct intr_vector *iv = arg; 377172066Smarius struct fhc_icarg *fica = iv->iv_icarg; 378170387Spiso 379178443Smarius bus_write_4(fica->fica_memres, FHC_IMAP, INTMAP_TID( 380178443Smarius bus_read_4(fica->fica_memres, FHC_IMAP), iv->iv_mid)); 381178443Smarius (void)bus_read_4(fica->fica_memres, FHC_IMAP); 382178443Smarius} 383178443Smarius 384178443Smariusstatic void 385178443Smariusfhc_intr_clear(void *arg) 386178443Smarius{ 387178443Smarius struct intr_vector *iv = arg; 388178443Smarius struct fhc_icarg *fica = iv->iv_icarg; 389178443Smarius 390172066Smarius bus_write_4(fica->fica_memres, FHC_ICLR, 0x0); 391172066Smarius (void)bus_read_4(fica->fica_memres, FHC_ICLR); 392170387Spiso} 393170387Spiso 394172066Smariusstatic int 395172066Smariusfhc_setup_intr(device_t bus, device_t child, struct resource *r, int flags, 396172066Smarius driver_filter_t *filt, driver_intr_t *func, void *arg, void **cookiep) 397111123Sjake{ 398172066Smarius struct fhc_softc *sc; 399172066Smarius u_long vec; 400111123Sjake 401172066Smarius sc = device_get_softc(bus); 402172066Smarius /* 403172066Smarius * Make sure the vector is fully specified and we registered 404172066Smarius * our interrupt controller for it. 405182070Smarius */ 406172066Smarius vec = rman_get_start(r); 407172066Smarius if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &fhc_ic) { 408172066Smarius device_printf(bus, "invalid interrupt vector 0x%lx\n", vec); 409182070Smarius return (EINVAL); 410182070Smarius } 411172066Smarius return (bus_generic_setup_intr(bus, child, r, flags, filt, func, 412172066Smarius arg, cookiep)); 413111123Sjake} 414111123Sjake 415167308Smariusstatic struct resource * 416111072Sjakefhc_alloc_resource(device_t bus, device_t child, int type, int *rid, 417111072Sjake u_long start, u_long end, u_long count, u_int flags) 418111072Sjake{ 419143826Smarius struct resource_list *rl; 420111072Sjake struct resource_list_entry *rle; 421111072Sjake struct fhc_softc *sc; 422111072Sjake struct resource *res; 423111072Sjake bus_addr_t coffset; 424111072Sjake bus_addr_t cend; 425111072Sjake bus_addr_t phys; 426111072Sjake int isdefault; 427143826Smarius int passthrough; 428111072Sjake int i; 429111072Sjake 430111072Sjake isdefault = (start == 0UL && end == ~0UL); 431143826Smarius passthrough = (device_get_parent(child) != bus); 432111072Sjake res = NULL; 433143826Smarius rle = NULL; 434143826Smarius rl = BUS_GET_RESOURCE_LIST(bus, child); 435111072Sjake sc = device_get_softc(bus); 436111072Sjake switch (type) { 437111072Sjake case SYS_RES_IRQ: 438143826Smarius return (resource_list_alloc(rl, bus, child, type, rid, start, 439143826Smarius end, count, flags)); 440111072Sjake case SYS_RES_MEMORY: 441143826Smarius if (!passthrough) { 442172066Smarius rle = resource_list_find(rl, type, *rid); 443143826Smarius if (rle == NULL) 444143826Smarius return (NULL); 445143826Smarius if (rle->res != NULL) 446143826Smarius panic("%s: resource entry is busy", __func__); 447143826Smarius if (isdefault) { 448143826Smarius start = rle->start; 449143826Smarius count = ulmax(count, rle->count); 450143826Smarius end = ulmax(rle->end, start + count - 1); 451143826Smarius } 452143826Smarius } 453111072Sjake for (i = 0; i < sc->sc_nrange; i++) { 454111072Sjake coffset = sc->sc_ranges[i].coffset; 455111072Sjake cend = coffset + sc->sc_ranges[i].size - 1; 456111072Sjake if (start >= coffset && end <= cend) { 457111072Sjake start -= coffset; 458111072Sjake end -= coffset; 459111072Sjake phys = sc->sc_ranges[i].poffset | 460111072Sjake ((bus_addr_t)sc->sc_ranges[i].pspace << 32); 461111072Sjake res = bus_generic_alloc_resource(bus, child, 462111072Sjake type, rid, phys + start, phys + end, 463111072Sjake count, flags); 464143826Smarius if (!passthrough) 465143826Smarius rle->res = res; 466111072Sjake break; 467111072Sjake } 468111072Sjake } 469111072Sjake break; 470111072Sjake } 471111072Sjake return (res); 472111072Sjake} 473111072Sjake 474167308Smariusstatic struct resource_list * 475143826Smariusfhc_get_resource_list(device_t bus, device_t child) 476111072Sjake{ 477111072Sjake struct fhc_devinfo *fdi; 478111072Sjake 479111072Sjake fdi = device_get_ivars(child); 480143826Smarius return (&fdi->fdi_rl); 481111072Sjake} 482133589Smarius 483167308Smariusstatic const struct ofw_bus_devinfo * 484152684Smariusfhc_get_devinfo(device_t bus, device_t child) 485152684Smarius{ 486152684Smarius struct fhc_devinfo *fdi; 487152684Smarius 488152684Smarius fdi = device_get_ivars(child); 489152684Smarius return (&fdi->fdi_obdinfo); 490152684Smarius} 491152684Smarius 492143826Smariusstatic void 493143826Smariusfhc_led_func(void *arg, int onoff) 494143826Smarius{ 495143826Smarius struct fhc_softc *sc; 496143826Smarius uint32_t ctrl; 497143826Smarius 498143826Smarius sc = (struct fhc_softc *)arg; 499143826Smarius 500172066Smarius ctrl = bus_read_4(sc->sc_memres[FHC_INTERNAL], FHC_CTRL); 501143826Smarius if (onoff) 502143826Smarius ctrl |= FHC_CTRL_RLED; 503143826Smarius else 504143826Smarius ctrl &= ~FHC_CTRL_RLED; 505143826Smarius ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE); 506172066Smarius bus_write_4(sc->sc_memres[FHC_INTERNAL], FHC_CTRL, ctrl); 507172066Smarius (void)bus_read_4(sc->sc_memres[FHC_INTERNAL], FHC_CTRL); 508143826Smarius} 509143826Smarius 510152684Smariusstatic int 511152684Smariusfhc_print_res(struct fhc_devinfo *fdi) 512133589Smarius{ 513152684Smarius int rv; 514133589Smarius 515152684Smarius rv = 0; 516152684Smarius rv += resource_list_print_type(&fdi->fdi_rl, "mem", SYS_RES_MEMORY, 517152684Smarius "%#lx"); 518152684Smarius rv += resource_list_print_type(&fdi->fdi_rl, "irq", SYS_RES_IRQ, "%ld"); 519152684Smarius return (rv); 520133589Smarius} 521