summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/arm/arm/nexus.c11
-rw-r--r--sys/arm/mv/mv_pci.c12
-rw-r--r--sys/conf/files1
-rw-r--r--sys/dev/fdt/fdt_common.c5
-rw-r--r--sys/dev/fdt/simplebus.c530
-rw-r--r--sys/dev/ofw/ofw_bus.h10
-rw-r--r--sys/dev/ofw/ofw_bus_if.m34
-rw-r--r--sys/dev/ofw/ofw_bus_subr.c27
-rw-r--r--sys/dev/ofw/ofw_bus_subr.h4
-rw-r--r--sys/dev/ofw/ofw_nexus.c5
-rw-r--r--sys/mips/beri/beri_simplebus.c425
-rw-r--r--sys/mips/beri/fdt_ic_if.m (renamed from sys/dev/fdt/fdt_ic_if.m)0
-rw-r--r--sys/mips/beri/files.beri2
-rw-r--r--sys/powerpc/ofw/ofw_pci.c4
-rw-r--r--sys/powerpc/ofw/ofw_pcib_pci.c6
-rw-r--r--sys/powerpc/ofw/ofw_pcibus.c36
-rw-r--r--sys/powerpc/powerpc/nexus.c17
-rw-r--r--sys/powerpc/pseries/vdevice.c2
18 files changed, 778 insertions, 353 deletions
diff --git a/sys/arm/arm/nexus.c b/sys/arm/arm/nexus.c
index 5200303..ec2c18f 100644
--- a/sys/arm/arm/nexus.c
+++ b/sys/arm/arm/nexus.c
@@ -98,7 +98,7 @@ static int nexus_teardown_intr(device_t, device_t, struct resource *, void *);
#ifdef FDT
static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent,
- int irq);
+ int icells, pcell_t *intr);
#endif
static device_method_t nexus_methods[] = {
@@ -339,15 +339,16 @@ nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
#ifdef FDT
static int
-nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int irq)
+nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
+ pcell_t *intr)
{
- pcell_t intr[2];
fdt_pic_decode_t intr_decode;
phandle_t intr_offset;
int i, rv, interrupt, trig, pol;
intr_offset = OF_xref_phandle(iparent);
- intr[0] = cpu_to_fdt32(irq);
+ for (i = 0; i < icells; i++)
+ intr[i] = cpu_to_fdt32(intr[i]);
for (i = 0; fdt_pic_table[i] != NULL; i++) {
intr_decode = fdt_pic_table[i];
@@ -361,7 +362,7 @@ nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int irq)
}
/* Not in table, so guess */
- interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(*intr));
+ interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(intr[0]));
return (interrupt);
}
diff --git a/sys/arm/mv/mv_pci.c b/sys/arm/mv/mv_pci.c
index 4660e5c..690ebb4 100644
--- a/sys/arm/mv/mv_pci.c
+++ b/sys/arm/mv/mv_pci.c
@@ -1050,7 +1050,8 @@ mv_pcib_route_interrupt(device_t bus, device_t dev, int pin)
{
struct mv_pcib_softc *sc;
struct ofw_pci_register reg;
- uint32_t pintr, mintr;
+ uint32_t pintr, mintr[4];
+ int icells;
phandle_t iparent;
sc = device_get_softc(bus);
@@ -1062,10 +1063,11 @@ mv_pcib_route_interrupt(device_t bus, device_t dev, int pin)
(pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
(pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
- if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
- sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
- &iparent))
- return (ofw_bus_map_intr(dev, iparent, mintr));
+ icells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo,
+ &reg, sizeof(reg), &pintr, sizeof(pintr), mintr, sizeof(mintr),
+ &iparent);
+ if (icells > 0)
+ return (ofw_bus_map_intr(dev, iparent, icells, mintr));
/* Maybe it's a real interrupt, not an intpin */
if (pin > 4)
diff --git a/sys/conf/files b/sys/conf/files
index ed2dd01..2aefaf3 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1404,7 +1404,6 @@ dev/fb/fbd.c optional fbd | vt
dev/fb/fb_if.m standard
dev/fb/splash.c optional sc splash
dev/fdt/fdt_common.c optional fdt
-dev/fdt/fdt_ic_if.m optional fdt
dev/fdt/fdt_slicer.c optional fdt cfi | fdt nand
dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static \
dependency "$S/boot/fdt/dts/${FDT_DTS_FILE}"
diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c
index 9d6840c..6cb5ac3 100644
--- a/sys/dev/fdt/fdt_common.c
+++ b/sys/dev/fdt/fdt_common.c
@@ -489,11 +489,10 @@ fdt_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl,
OF_searchencprop(OF_xref_phandle(iparent), "#interrupt-cells",
&icells, sizeof(icells));
for (i = 0, k = 0; i < nintr; i += icells, k++) {
- intr[i] = ofw_bus_map_intr(dev, iparent, intr[i]);
+ intr[i] = ofw_bus_map_intr(dev, iparent, icells,
+ &intr[i]);
resource_list_add(rl, SYS_RES_IRQ, k, intr[i], intr[i],
1);
- if (icells > 1)
- ofw_bus_config_intr(dev, intr[i], intr[i+1]);
}
free(intr, M_OFWPROP);
}
diff --git a/sys/dev/fdt/simplebus.c b/sys/dev/fdt/simplebus.c
index b0f8fee..5661d81 100644
--- a/sys/dev/fdt/simplebus.c
+++ b/sys/dev/fdt/simplebus.c
@@ -1,10 +1,7 @@
/*-
- * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * Copyright (c) 2013 Nathan Whitehorn
* All rights reserved.
*
- * This software was developed by Semihalf under sponsorship from
- * the FreeBSD Foundation.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +14,7 @@
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -29,95 +26,85 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-
-#include "opt_platform.h"
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/ktr.h>
-#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
#include <sys/rman.h>
-#include <sys/malloc.h>
+#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <dev/ofw/openfirm.h>
-#include "fdt_common.h"
-#include "fdt_ic_if.h"
-#include "ofw_bus_if.h"
+struct simplebus_range {
+ uint64_t bus;
+ uint64_t host;
+ uint64_t size;
+};
-#ifdef DEBUG
-#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
- printf(fmt,##args); } while (0)
-#else
-#define debugf(fmt, args...)
-#endif
+struct simplebus_softc {
+ device_t dev;
+ phandle_t node;
-static MALLOC_DEFINE(M_SIMPLEBUS, "simplebus", "simplebus devices information");
+ struct simplebus_range *ranges;
+ int nranges;
-struct simplebus_softc {
- int sc_addr_cells;
- int sc_size_cells;
+ pcell_t acells, scells;
};
struct simplebus_devinfo {
- struct ofw_bus_devinfo di_ofw;
- struct resource_list di_res;
-
- /* Interrupts sense-level info for this device */
- struct fdt_sense_level di_intr_sl[DI_MAX_INTR_NUM];
+ struct ofw_bus_devinfo obdinfo;
+ struct resource_list rl;
};
/*
- * Prototypes.
+ * Bus interface.
*/
-static int simplebus_probe(device_t);
-static int simplebus_attach(device_t);
-
-static int simplebus_print_child(device_t, device_t);
-static int simplebus_setup_intr(device_t, device_t, struct resource *, int,
- driver_filter_t *, driver_intr_t *, void *, void **);
-static int simplebus_teardown_intr(device_t, device_t, struct resource *,
- void *);
-
-static int simplebus_activate_resource(device_t, device_t, int, int,
- struct resource *);
+static int simplebus_probe(device_t dev);
+static int simplebus_attach(device_t dev);
static struct resource *simplebus_alloc_resource(device_t, device_t, int,
int *, u_long, u_long, u_long, u_int);
-static int simplebus_deactivate_resource(device_t, device_t, int, int,
- struct resource *);
-static int simplebus_release_resource(device_t, device_t, int, int,
- struct resource *);
-static device_t simplebus_get_interrupt_parent(device_t);
-static struct resource_list *simplebus_get_resource_list(device_t, device_t);
+static void simplebus_probe_nomatch(device_t bus, device_t child);
+static int simplebus_print_child(device_t bus, device_t child);
-static ofw_bus_get_devinfo_t simplebus_get_devinfo;
+/*
+ * ofw_bus interface
+ */
+static const struct ofw_bus_devinfo *simplebus_get_devinfo(device_t bus,
+ device_t child);
/*
- * Bus interface definition.
+ * local methods
*/
-static device_method_t simplebus_methods[] = {
+
+static int simplebus_fill_ranges(phandle_t node,
+ struct simplebus_softc *sc);
+static struct simplebus_devinfo *simplebus_setup_dinfo(device_t dev,
+ phandle_t node);
+
+/*
+ * Driver methods.
+ */
+static device_method_t simplebus_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, simplebus_probe),
DEVMETHOD(device_attach, simplebus_attach),
- DEVMETHOD(device_detach, bus_generic_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
DEVMETHOD(bus_print_child, simplebus_print_child),
+ DEVMETHOD(bus_probe_nomatch, simplebus_probe_nomatch),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_alloc_resource, simplebus_alloc_resource),
- DEVMETHOD(bus_release_resource, simplebus_release_resource),
- DEVMETHOD(bus_activate_resource, simplebus_activate_resource),
- DEVMETHOD(bus_deactivate_resource, simplebus_deactivate_resource),
- DEVMETHOD(bus_setup_intr, simplebus_setup_intr),
- DEVMETHOD(bus_teardown_intr, simplebus_teardown_intr),
- DEVMETHOD(bus_get_resource_list, simplebus_get_resource_list),
-
- /* OFW bus interface */
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
+
+ /* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, simplebus_get_devinfo),
DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
@@ -125,7 +112,7 @@ static device_method_t simplebus_methods[] = {
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t simplebus_driver = {
@@ -133,18 +120,17 @@ static driver_t simplebus_driver = {
simplebus_methods,
sizeof(struct simplebus_softc)
};
-
-devclass_t simplebus_devclass;
-
+static devclass_t simplebus_devclass;
DRIVER_MODULE(simplebus, nexus, simplebus_driver, simplebus_devclass, 0, 0);
-DRIVER_MODULE(simplebus, simplebus, simplebus_driver, simplebus_devclass, 0,
- 0);
+DRIVER_MODULE(simplebus, simplebus, simplebus_driver, simplebus_devclass, 0, 0);
static int
simplebus_probe(device_t dev)
{
-
- if (!ofw_bus_is_compatible(dev, "simple-bus"))
+
+ if (!ofw_bus_is_compatible(dev, "simple-bus") &&
+ (ofw_bus_get_type(dev) == NULL || strcmp(ofw_bus_get_type(dev),
+ "soc") != 0))
return (ENXIO);
device_set_desc(dev, "Flattened device tree simple bus");
@@ -155,102 +141,200 @@ simplebus_probe(device_t dev)
static int
simplebus_attach(device_t dev)
{
- device_t dev_child;
- struct simplebus_devinfo *di;
- struct simplebus_softc *sc;
- phandle_t dt_node, dt_child;
+ struct simplebus_softc *sc;
+ struct simplebus_devinfo *di;
+ phandle_t node;
+ device_t cdev;
+ node = ofw_bus_get_node(dev);
sc = device_get_softc(dev);
+ sc->dev = dev;
+ sc->node = node;
+
/*
- * Walk simple-bus and add direct subordinates as our children.
+ * Some important numbers
*/
- dt_node = ofw_bus_get_node(dev);
- for (dt_child = OF_child(dt_node); dt_child != 0;
- dt_child = OF_peer(dt_child)) {
-
- /* Check and process 'status' property. */
- if (!(fdt_is_enabled(dt_child)))
- continue;
+ sc->acells = 2;
+ OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells));
+ sc->scells = 1;
+ OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells));
- if (!(fdt_pm_is_enabled(dt_child)))
- continue;
+ if (simplebus_fill_ranges(node, sc) < 0) {
+ device_printf(dev, "could not get ranges\n");
+ return (ENXIO);
+ }
- di = malloc(sizeof(*di), M_SIMPLEBUS, M_WAITOK | M_ZERO);
+ /*
+ * In principle, simplebus could have an interrupt map, but ignore that
+ * for now
+ */
- if (ofw_bus_gen_setup_devinfo(&di->di_ofw, dt_child) != 0) {
- free(di, M_SIMPLEBUS);
- device_printf(dev, "could not set up devinfo\n");
+ for (node = OF_child(node); node > 0; node = OF_peer(node)) {
+ if ((di = simplebus_setup_dinfo(dev, node)) == NULL)
continue;
- }
-
- resource_list_init(&di->di_res);
- if (fdt_reg_to_rl(dt_child, &di->di_res)) {
- device_printf(dev,
- "%s: could not process 'reg' "
- "property\n", di->di_ofw.obd_name);
- ofw_bus_gen_destroy_devinfo(&di->di_ofw);
- free(di, M_SIMPLEBUS);
+ cdev = device_add_child(dev, NULL, -1);
+ if (cdev == NULL) {
+ device_printf(dev, "<%s>: device_add_child failed\n",
+ di->obdinfo.obd_name);
+ resource_list_free(&di->rl);
+ ofw_bus_gen_destroy_devinfo(&di->obdinfo);
+ free(di, M_DEVBUF);
continue;
}
+ device_set_ivars(cdev, di);
+ }
- if (fdt_intr_to_rl(dev, dt_child, &di->di_res, di->di_intr_sl)) {
- device_printf(dev, "%s: could not process "
- "'interrupts' property\n", di->di_ofw.obd_name);
- resource_list_free(&di->di_res);
- ofw_bus_gen_destroy_devinfo(&di->di_ofw);
- free(di, M_SIMPLEBUS);
- continue;
- }
+ return (bus_generic_attach(dev));
+}
- /* Add newbus device for this FDT node */
- dev_child = device_add_child(dev, NULL, -1);
- if (dev_child == NULL) {
- device_printf(dev, "could not add child: %s\n",
- di->di_ofw.obd_name);
- resource_list_free(&di->di_res);
- ofw_bus_gen_destroy_devinfo(&di->di_ofw);
- free(di, M_SIMPLEBUS);
- continue;
+static int
+simplebus_fill_ranges(phandle_t node, struct simplebus_softc *sc)
+{
+ int host_address_cells;
+ cell_t *base_ranges;
+ ssize_t nbase_ranges;
+ int err;
+ int i, j, k;
+
+ err = OF_searchencprop(OF_parent(node), "#address-cells",
+ &host_address_cells, sizeof(host_address_cells));
+ if (err <= 0)
+ return (-1);
+
+ nbase_ranges = OF_getproplen(node, "ranges");
+ if (nbase_ranges < 0)
+ return (-1);
+ sc->nranges = nbase_ranges / sizeof(cell_t) /
+ (sc->acells + host_address_cells + sc->scells);
+ if (sc->nranges == 0)
+ return (0);
+
+ sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]),
+ M_DEVBUF, M_WAITOK);
+ base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
+ OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
+
+ for (i = 0, j = 0; i < sc->nranges; i++) {
+ sc->ranges[i].bus = 0;
+ for (k = 0; k < sc->acells; k++) {
+ sc->ranges[i].bus <<= 32;
+ sc->ranges[i].bus |= base_ranges[j++];
+ }
+ sc->ranges[i].host = 0;
+ for (k = 0; k < host_address_cells; k++) {
+ sc->ranges[i].host <<= 32;
+ sc->ranges[i].host |= base_ranges[j++];
+ }
+ sc->ranges[i].size = 0;
+ for (k = 0; k < sc->scells; k++) {
+ sc->ranges[i].size <<= 32;
+ sc->ranges[i].size |= base_ranges[j++];
}
-#ifdef DEBUG
- device_printf(dev, "added child: %s\n\n", di->di_ofw.obd_name);
-#endif
- device_set_ivars(dev_child, di);
}
- return (bus_generic_attach(dev));
+ free(base_ranges, M_DEVBUF);
+ return (sc->nranges);
}
-static int
-simplebus_print_child(device_t dev, device_t child)
+static struct simplebus_devinfo *
+simplebus_setup_dinfo(device_t dev, phandle_t node)
{
- device_t ip;
- struct simplebus_devinfo *di;
- struct resource_list *rl;
- int rv;
+ struct simplebus_softc *sc;
+ struct simplebus_devinfo *ndi;
+ uint32_t *reg, *intr, icells;
+ uint64_t phys, size;
+ phandle_t iparent;
+ int i, j, k;
+ int nintr;
+ int nreg;
- di = device_get_ivars(child);
- rl = &di->di_res;
+ sc = device_get_softc(dev);
- rv = 0;
- rv += bus_print_child_header(dev, child);
- rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
- if ((ip = simplebus_get_interrupt_parent(child)) != NULL)
- rv += printf(" (%s)", device_get_nameunit(ip));
- rv += bus_print_child_footer(dev, child);
+ ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
+ if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) {
+ free(ndi, M_DEVBUF);
+ return (NULL);
+ }
- return (rv);
+ resource_list_init(&ndi->rl);
+ nreg = OF_getencprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
+ if (nreg == -1)
+ nreg = 0;
+ if (nreg % (sc->acells + sc->scells) != 0) {
+ if (bootverbose)
+ device_printf(dev, "Malformed reg property on <%s>\n",
+ ndi->obdinfo.obd_name);
+ nreg = 0;
+ }
+
+ for (i = 0, k = 0; i < nreg; i += sc->acells + sc->scells, k++) {
+ phys = size = 0;
+ for (j = 0; j < sc->acells; j++) {
+ phys <<= 32;
+ phys |= reg[i + j];
+ }
+ for (j = 0; j < sc->scells; j++) {
+ size <<= 32;
+ size |= reg[i + sc->acells + j];
+ }
+
+ resource_list_add(&ndi->rl, SYS_RES_MEMORY, k,
+ phys, phys + size - 1, size);
+ }
+ free(reg, M_OFWPROP);
+
+ nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr),
+ (void **)&intr);
+ if (nintr > 0) {
+ if (OF_searchencprop(node, "interrupt-parent", &iparent,
+ sizeof(iparent)) == -1) {
+ device_printf(dev, "No interrupt-parent found, "
+ "assuming direct parent\n");
+ iparent = OF_parent(node);
+ }
+ if (OF_searchencprop(OF_xref_phandle(iparent),
+ "#interrupt-cells", &icells, sizeof(icells)) == -1) {
+ device_printf(dev, "Missing #interrupt-cells property, "
+ "assuming <1>\n");
+ icells = 1;
+ }
+ if (icells < 1 || icells > nintr) {
+ device_printf(dev, "Invalid #interrupt-cells property "
+ "value <%d>, assuming <1>\n", icells);
+ icells = 1;
+ }
+ for (i = 0, k = 0; i < nintr; i += icells, k++) {
+ intr[i] = ofw_bus_map_intr(dev, iparent, icells,
+ &intr[i]);
+ resource_list_add(&ndi->rl, SYS_RES_IRQ, k, intr[i],
+ intr[i], 1);
+ }
+ free(intr, M_OFWPROP);
+ }
+
+ return (ndi);
+}
+
+static const struct ofw_bus_devinfo *
+simplebus_get_devinfo(device_t bus __unused, device_t child)
+{
+ struct simplebus_devinfo *ndi;
+
+ ndi = device_get_ivars(child);
+ return (&ndi->obdinfo);
}
static struct resource *
simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
- device_t ic;
+ struct simplebus_softc *sc;
struct simplebus_devinfo *di;
struct resource_list_entry *rle;
+ int j;
+
+ sc = device_get_softc(bus);
/*
* Request for the default allocation with a given rid: use resource
@@ -263,7 +347,7 @@ simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
if (type == SYS_RES_IOPORT)
type = SYS_RES_MEMORY;
- rle = resource_list_find(&di->di_res, type, *rid);
+ rle = resource_list_find(&di->rl, type, *rid);
if (rle == NULL) {
if (bootverbose)
device_printf(bus, "no default resources for "
@@ -273,153 +357,69 @@ simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
start = rle->start;
end = rle->end;
count = rle->count;
- }
+ }
+
+ if (type == SYS_RES_MEMORY) {
+ /* Remap through ranges property */
+ for (j = 0; j < sc->nranges; j++) {
+ if (start >= sc->ranges[j].bus && end <
+ sc->ranges[j].bus + sc->ranges[j].size) {
+ start -= sc->ranges[j].bus;
+ start += sc->ranges[j].host;
+ end -= sc->ranges[j].bus;
+ end += sc->ranges[j].host;
+ break;
+ }
+ }
+ if (j == sc->nranges && sc->nranges != 0) {
+ if (bootverbose)
+ device_printf(bus, "Could not map resource "
+ "%#lx-%#lx\n", start, end);
- if (type == SYS_RES_IRQ &&
- (ic = simplebus_get_interrupt_parent(child)) != NULL)
- return(FDT_IC_ALLOC_INTR(ic, child, rid, start, flags));
+ return (NULL);
+ }
+ }
return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
count, flags));
}
static int
-simplebus_activate_resource(device_t dev, device_t child, int type, int rid,
- struct resource *r)
-{
- device_t ic;
-
- if (type == SYS_RES_IRQ &&
- (ic = simplebus_get_interrupt_parent(child)) != NULL)
- return (FDT_IC_ACTIVATE_INTR(ic, r));
-
- return (bus_generic_activate_resource(dev, child, type, rid, r));
-}
-
-static int
-simplebus_deactivate_resource(device_t dev, device_t child, int type, int rid,
- struct resource *r)
-{
- device_t ic;
-
- if (type == SYS_RES_IRQ &&
- (ic = simplebus_get_interrupt_parent(child)) != NULL)
- return (FDT_IC_DEACTIVATE_INTR(ic, r));
-
- return (bus_generic_deactivate_resource(dev, child, type, rid, r));
-}
-
-static int
-simplebus_release_resource(device_t dev, device_t child, int type, int rid,
- struct resource *r)
-{
- device_t ic;
-
- if (type == SYS_RES_IRQ &&
- (ic = simplebus_get_interrupt_parent(child)) != NULL)
- return (FDT_IC_RELEASE_INTR(ic, r));
-
- return (bus_generic_release_resource(dev, child, type, rid, r));
-}
-
-static struct resource_list *
-simplebus_get_resource_list(device_t bus, device_t child)
-{
- struct simplebus_devinfo *di;
-
- di = device_get_ivars(child);
- return (&di->di_res);
-}
-
-static device_t
-simplebus_get_interrupt_parent(device_t dev)
+simplebus_print_res(struct simplebus_devinfo *di)
{
- struct simplebus_devinfo *di;
- struct fdt_ic *ic;
- device_t ip;
- phandle_t ph, iph;
-
- ip = NULL;
-
- di = device_get_ivars(dev);
- if (di == NULL)
- return (NULL);
+ int rv;
- if (OF_getencprop(di->di_ofw.obd_node, "interrupt-parent", &iph,
- sizeof(iph)) > 0) {
- ph = OF_xref_phandle(iph);
- SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) {
- if (ic->iph == ph) {
- ip = ic->dev;
- break;
- }
- }
- }
- return (ip);
+ rv = 0;
+ rv += resource_list_print_type(&di->rl, "mem", SYS_RES_MEMORY, "%#lx");
+ rv += resource_list_print_type(&di->rl, "irq", SYS_RES_IRQ, "%ld");
+ return (rv);
}
-static int
-simplebus_setup_intr(device_t bus, device_t child, struct resource *res,
- int flags, driver_filter_t *filter, driver_intr_t *ihand, void *arg,
- void **cookiep)
+static void
+simplebus_probe_nomatch(device_t bus, device_t child)
{
- struct simplebus_devinfo *di;
- device_t ic;
- enum intr_trigger trig;
- enum intr_polarity pol;
- int error, irq, rid;
+ const char *name, *type;
- di = device_get_ivars(child);
- if (di == NULL)
- return (ENXIO);
+ if (!bootverbose)
+ return;
- if (res == NULL)
- return (EINVAL);
-
- rid = rman_get_rid(res);
- if (rid >= DI_MAX_INTR_NUM)
- return (ENOENT);
-
- ic = simplebus_get_interrupt_parent(child);
-
- trig = di->di_intr_sl[rid].trig;
- pol = di->di_intr_sl[rid].pol;
- if (trig != INTR_TRIGGER_CONFORM || pol != INTR_POLARITY_CONFORM) {
- irq = rman_get_start(res);
- if (ic != NULL)
- error = FDT_IC_CONFIG_INTR(ic, irq, trig, pol);
- else
- error = bus_generic_config_intr(bus, irq, trig, pol);
- if (error)
- return (error);
- }
+ name = ofw_bus_get_name(child);
+ type = ofw_bus_get_type(child);
- if (ic != NULL)
- error = FDT_IC_SETUP_INTR(ic, child, res, flags, filter,
- ihand, arg, cookiep);
- else
- error = bus_generic_setup_intr(bus, child, res, flags, filter,
- ihand, arg, cookiep);
- return (error);
+ device_printf(bus, "<%s>", name != NULL ? name : "unknown");
+ simplebus_print_res(device_get_ivars(child));
+ printf(" type %s (no driver attached)\n",
+ type != NULL ? type : "unknown");
}
static int
-simplebus_teardown_intr(device_t bus, device_t child, struct resource *res,
- void *cookie)
+simplebus_print_child(device_t bus, device_t child)
{
- device_t ic;
-
- if ((ic = simplebus_get_interrupt_parent(child)) != NULL)
- return (FDT_IC_TEARDOWN_INTR(ic, child, res, cookie));
+ int rv;
- return (bus_generic_teardown_intr(bus, child, res, cookie));
+ rv = bus_print_child_header(bus, child);
+ rv += simplebus_print_res(device_get_ivars(child));
+ rv += bus_print_child_footer(bus, child);
+ return (rv);
}
-static const struct ofw_bus_devinfo *
-simplebus_get_devinfo(device_t bus, device_t child)
-{
- struct simplebus_devinfo *di;
-
- di = device_get_ivars(child);
- return (&di->di_ofw);
-}
diff --git a/sys/dev/ofw/ofw_bus.h b/sys/dev/ofw/ofw_bus.h
index 1ea4845..f7c7295 100644
--- a/sys/dev/ofw/ofw_bus.h
+++ b/sys/dev/ofw/ofw_bus.h
@@ -71,15 +71,9 @@ ofw_bus_get_type(device_t dev)
}
static __inline int
-ofw_bus_map_intr(device_t dev, phandle_t iparent, int irq)
+ofw_bus_map_intr(device_t dev, phandle_t iparent, int icells, pcell_t *intr)
{
- return (OFW_BUS_MAP_INTR(dev, dev, iparent, irq));
-}
-
-static __inline int
-ofw_bus_config_intr(device_t dev, int irq, int sense)
-{
- return (OFW_BUS_CONFIG_INTR(dev, dev, irq, sense));
+ return (OFW_BUS_MAP_INTR(dev, dev, iparent, icells, intr));
}
#endif /* !_DEV_OFW_OFW_BUS_H_ */
diff --git a/sys/dev/ofw/ofw_bus_if.m b/sys/dev/ofw/ofw_bus_if.m
index 0034a15..6486e96 100644
--- a/sys/dev/ofw/ofw_bus_if.m
+++ b/sys/dev/ofw/ofw_bus_if.m
@@ -46,6 +46,7 @@ HEADER {
char *obd_model;
char *obd_name;
char *obd_type;
+ char *obd_status;
};
};
@@ -57,7 +58,6 @@ CODE {
static ofw_bus_get_node_t ofw_bus_default_get_node;
static ofw_bus_get_type_t ofw_bus_default_get_type;
static ofw_bus_map_intr_t ofw_bus_default_map_intr;
- static ofw_bus_config_intr_t ofw_bus_default_config_intr;
static const struct ofw_bus_devinfo *
ofw_bus_default_get_devinfo(device_t bus, device_t dev)
@@ -103,27 +103,15 @@ CODE {
int
ofw_bus_default_map_intr(device_t bus, device_t dev, phandle_t iparent,
- int irq)
+ int icells, pcell_t *interrupt)
{
/* Propagate up the bus hierarchy until someone handles it. */
if (device_get_parent(bus) != NULL)
return OFW_BUS_MAP_INTR(device_get_parent(bus), dev,
- iparent, irq);
+ iparent, icells, interrupt);
/* If that fails, then assume a one-domain system */
- return (irq);
- }
-
- int
- ofw_bus_default_config_intr(device_t bus, device_t dev, int irq,
- int sense)
- {
- /* Propagate up the bus hierarchy until someone handles it. */
- if (device_get_parent(bus) != NULL)
- return OFW_BUS_CONFIG_INTR(device_get_parent(bus), dev,
- irq, sense);
-
- return (ENXIO);
+ return (interrupt[0]);
}
};
@@ -172,20 +160,14 @@ METHOD const char * get_type {
} DEFAULT ofw_bus_default_get_type;
# Map an (interrupt parent, IRQ) pair to a unique system-wide interrupt number.
+# If the interrupt encoding includes a sense field, the interrupt sense will
+# also be configured.
METHOD int map_intr {
device_t bus;
device_t dev;
phandle_t iparent;
- int irq;
+ int icells;
+ pcell_t *interrupt;
} DEFAULT ofw_bus_default_map_intr;
-# Configure an interrupt using the device-tree encoded sense key (the second
-# value in the interrupts property if interrupt-cells is 2). IRQ should be
-# encoded as from ofw_bus_map_intr().
-METHOD int config_intr {
- device_t bus;
- device_t dev;
- int irq;
- int sense;
-} DEFAULT ofw_bus_default_config_intr;
diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c
index bf552a8..64ac11f 100644
--- a/sys/dev/ofw/ofw_bus_subr.c
+++ b/sys/dev/ofw/ofw_bus_subr.c
@@ -55,6 +55,7 @@ ofw_bus_gen_setup_devinfo(struct ofw_bus_devinfo *obd, phandle_t node)
OF_getprop_alloc(node, "compatible", 1, (void **)&obd->obd_compat);
OF_getprop_alloc(node, "device_type", 1, (void **)&obd->obd_type);
OF_getprop_alloc(node, "model", 1, (void **)&obd->obd_model);
+ OF_getprop_alloc(node, "status", 1, (void **)&obd->obd_status);
obd->obd_node = node;
return (0);
}
@@ -73,6 +74,8 @@ ofw_bus_gen_destroy_devinfo(struct ofw_bus_devinfo *obd)
free(obd->obd_name, M_OFWPROP);
if (obd->obd_type != NULL)
free(obd->obd_type, M_OFWPROP);
+ if (obd->obd_status != NULL)
+ free(obd->obd_status, M_OFWPROP);
}
int
@@ -147,6 +150,30 @@ ofw_bus_gen_get_type(device_t bus, device_t dev)
return (obd->obd_type);
}
+const char *
+ofw_bus_get_status(device_t dev)
+{
+ const struct ofw_bus_devinfo *obd;
+
+ obd = OFW_BUS_GET_DEVINFO(device_get_parent(dev), dev);
+ if (obd == NULL)
+ return (NULL);
+
+ return (obd->obd_status);
+}
+
+int
+ofw_bus_status_okay(device_t dev)
+{
+ const char *status;
+
+ status = ofw_bus_get_status(dev);
+ if (status == NULL || strcmp(status, "okay") == 0)
+ return (1);
+
+ return (0);
+}
+
int
ofw_bus_is_compatible(device_t dev, const char *onecompat)
{
diff --git a/sys/dev/ofw/ofw_bus_subr.h b/sys/dev/ofw/ofw_bus_subr.h
index e9ef5e4..a4d8b92 100644
--- a/sys/dev/ofw/ofw_bus_subr.h
+++ b/sys/dev/ofw/ofw_bus_subr.h
@@ -72,6 +72,10 @@ int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int,
int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *,
void *, void *, int, phandle_t *);
+/* Helper to get device status property */
+const char *ofw_bus_get_status(device_t dev);
+int ofw_bus_status_okay(device_t dev);
+
/* Helper to get node's interrupt parent */
void ofw_bus_find_iparent(phandle_t);
diff --git a/sys/dev/ofw/ofw_nexus.c b/sys/dev/ofw/ofw_nexus.c
index f602bfe..b3c5e03 100644
--- a/sys/dev/ofw/ofw_nexus.c
+++ b/sys/dev/ofw/ofw_nexus.c
@@ -467,11 +467,10 @@ nexus_setup_dinfo(device_t dev, phandle_t node)
OF_searchencprop(OF_xref_phandle(iparent), "#interrupt-cells",
&icells, sizeof(icells));
for (i = 0; i < nintr; i+= icells) {
- intr[i] = ofw_bus_map_intr(dev, iparent, intr[i]);
+ intr[i] = ofw_bus_map_intr(dev, iparent, icells,
+ &intr[i]);
resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],
intr[i], 1);
- if (icells > 1)
- ofw_bus_config_intr(dev, intr[i], intr[i+1]);
}
free(intr, M_OFWPROP);
}
diff --git a/sys/mips/beri/beri_simplebus.c b/sys/mips/beri/beri_simplebus.c
new file mode 100644
index 0000000..58927f9
--- /dev/null
+++ b/sys/mips/beri/beri_simplebus.c
@@ -0,0 +1,425 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Semihalf under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_platform.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ktr.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/malloc.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include <dev/fdt/fdt_common.h>
+#include "fdt_ic_if.h"
+#include "ofw_bus_if.h"
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
+ printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+static MALLOC_DEFINE(M_SIMPLEBUS, "simplebus", "simplebus devices information");
+
+struct simplebus_softc {
+ int sc_addr_cells;
+ int sc_size_cells;
+};
+
+struct simplebus_devinfo {
+ struct ofw_bus_devinfo di_ofw;
+ struct resource_list di_res;
+
+ /* Interrupts sense-level info for this device */
+ struct fdt_sense_level di_intr_sl[DI_MAX_INTR_NUM];
+};
+
+/*
+ * Prototypes.
+ */
+static int simplebus_probe(device_t);
+static int simplebus_attach(device_t);
+
+static int simplebus_print_child(device_t, device_t);
+static int simplebus_setup_intr(device_t, device_t, struct resource *, int,
+ driver_filter_t *, driver_intr_t *, void *, void **);
+static int simplebus_teardown_intr(device_t, device_t, struct resource *,
+ void *);
+
+static int simplebus_activate_resource(device_t, device_t, int, int,
+ struct resource *);
+static struct resource *simplebus_alloc_resource(device_t, device_t, int,
+ int *, u_long, u_long, u_long, u_int);
+static int simplebus_deactivate_resource(device_t, device_t, int, int,
+ struct resource *);
+static int simplebus_release_resource(device_t, device_t, int, int,
+ struct resource *);
+static device_t simplebus_get_interrupt_parent(device_t);
+static struct resource_list *simplebus_get_resource_list(device_t, device_t);
+
+static ofw_bus_get_devinfo_t simplebus_get_devinfo;
+
+/*
+ * Bus interface definition.
+ */
+static device_method_t simplebus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, simplebus_probe),
+ DEVMETHOD(device_attach, simplebus_attach),
+ DEVMETHOD(device_detach, bus_generic_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, simplebus_print_child),
+ DEVMETHOD(bus_alloc_resource, simplebus_alloc_resource),
+ DEVMETHOD(bus_release_resource, simplebus_release_resource),
+ DEVMETHOD(bus_activate_resource, simplebus_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, simplebus_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, simplebus_setup_intr),
+ DEVMETHOD(bus_teardown_intr, simplebus_teardown_intr),
+ DEVMETHOD(bus_get_resource_list, simplebus_get_resource_list),
+
+ /* OFW bus interface */
+ DEVMETHOD(ofw_bus_get_devinfo, simplebus_get_devinfo),
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+
+ { 0, 0 }
+};
+
+static driver_t simplebus_driver = {
+ "simplebus",
+ simplebus_methods,
+ sizeof(struct simplebus_softc)
+};
+
+devclass_t simplebus_devclass;
+
+DRIVER_MODULE(simplebus, nexus, simplebus_driver, simplebus_devclass, 0, 0);
+DRIVER_MODULE(simplebus, simplebus, simplebus_driver, simplebus_devclass, 0,
+ 0);
+
+static int
+simplebus_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible(dev, "simple-bus"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Flattened device tree simple bus");
+
+ return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+simplebus_attach(device_t dev)
+{
+ device_t dev_child;
+ struct simplebus_devinfo *di;
+ struct simplebus_softc *sc;
+ phandle_t dt_node, dt_child;
+
+ sc = device_get_softc(dev);
+
+ /*
+ * Walk simple-bus and add direct subordinates as our children.
+ */
+ dt_node = ofw_bus_get_node(dev);
+ for (dt_child = OF_child(dt_node); dt_child != 0;
+ dt_child = OF_peer(dt_child)) {
+
+ /* Check and process 'status' property. */
+ if (!(fdt_is_enabled(dt_child)))
+ continue;
+
+ if (!(fdt_pm_is_enabled(dt_child)))
+ continue;
+
+ di = malloc(sizeof(*di), M_SIMPLEBUS, M_WAITOK | M_ZERO);
+
+ if (ofw_bus_gen_setup_devinfo(&di->di_ofw, dt_child) != 0) {
+ free(di, M_SIMPLEBUS);
+ device_printf(dev, "could not set up devinfo\n");
+ continue;
+ }
+
+ resource_list_init(&di->di_res);
+ if (fdt_reg_to_rl(dt_child, &di->di_res)) {
+ device_printf(dev,
+ "%s: could not process 'reg' "
+ "property\n", di->di_ofw.obd_name);
+ ofw_bus_gen_destroy_devinfo(&di->di_ofw);
+ free(di, M_SIMPLEBUS);
+ continue;
+ }
+
+ if (fdt_intr_to_rl(dev, dt_child, &di->di_res, di->di_intr_sl)) {
+ device_printf(dev, "%s: could not process "
+ "'interrupts' property\n", di->di_ofw.obd_name);
+ resource_list_free(&di->di_res);
+ ofw_bus_gen_destroy_devinfo(&di->di_ofw);
+ free(di, M_SIMPLEBUS);
+ continue;
+ }
+
+ /* Add newbus device for this FDT node */
+ dev_child = device_add_child(dev, NULL, -1);
+ if (dev_child == NULL) {
+ device_printf(dev, "could not add child: %s\n",
+ di->di_ofw.obd_name);
+ resource_list_free(&di->di_res);
+ ofw_bus_gen_destroy_devinfo(&di->di_ofw);
+ free(di, M_SIMPLEBUS);
+ continue;
+ }
+#ifdef DEBUG
+ device_printf(dev, "added child: %s\n\n", di->di_ofw.obd_name);
+#endif
+ device_set_ivars(dev_child, di);
+ }
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+simplebus_print_child(device_t dev, device_t child)
+{
+ device_t ip;
+ struct simplebus_devinfo *di;
+ struct resource_list *rl;
+ int rv;
+
+ di = device_get_ivars(child);
+ rl = &di->di_res;
+
+ rv = 0;
+ rv += bus_print_child_header(dev, child);
+ rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
+ rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ if ((ip = simplebus_get_interrupt_parent(child)) != NULL)
+ rv += printf(" (%s)", device_get_nameunit(ip));
+ rv += bus_print_child_footer(dev, child);
+
+ return (rv);
+}
+
+static struct resource *
+simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ device_t ic;
+ struct simplebus_devinfo *di;
+ struct resource_list_entry *rle;
+
+ /*
+ * Request for the default allocation with a given rid: use resource
+ * list stored in the local device info.
+ */
+ if ((start == 0UL) && (end == ~0UL)) {
+ if ((di = device_get_ivars(child)) == NULL)
+ return (NULL);
+
+ if (type == SYS_RES_IOPORT)
+ type = SYS_RES_MEMORY;
+
+ rle = resource_list_find(&di->di_res, type, *rid);
+ if (rle == NULL) {
+ if (bootverbose)
+ device_printf(bus, "no default resources for "
+ "rid = %d, type = %d\n", *rid, type);
+ return (NULL);
+ }
+ start = rle->start;
+ end = rle->end;
+ count = rle->count;
+ }
+
+ if (type == SYS_RES_IRQ &&
+ (ic = simplebus_get_interrupt_parent(child)) != NULL)
+ return(FDT_IC_ALLOC_INTR(ic, child, rid, start, flags));
+
+ return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
+ count, flags));
+}
+
+static int
+simplebus_activate_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ device_t ic;
+
+ if (type == SYS_RES_IRQ &&
+ (ic = simplebus_get_interrupt_parent(child)) != NULL)
+ return (FDT_IC_ACTIVATE_INTR(ic, r));
+
+ return (bus_generic_activate_resource(dev, child, type, rid, r));
+}
+
+static int
+simplebus_deactivate_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ device_t ic;
+
+ if (type == SYS_RES_IRQ &&
+ (ic = simplebus_get_interrupt_parent(child)) != NULL)
+ return (FDT_IC_DEACTIVATE_INTR(ic, r));
+
+ return (bus_generic_deactivate_resource(dev, child, type, rid, r));
+}
+
+static int
+simplebus_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ device_t ic;
+
+ if (type == SYS_RES_IRQ &&
+ (ic = simplebus_get_interrupt_parent(child)) != NULL)
+ return (FDT_IC_RELEASE_INTR(ic, r));
+
+ return (bus_generic_release_resource(dev, child, type, rid, r));
+}
+
+static struct resource_list *
+simplebus_get_resource_list(device_t bus, device_t child)
+{
+ struct simplebus_devinfo *di;
+
+ di = device_get_ivars(child);
+ return (&di->di_res);
+}
+
+static device_t
+simplebus_get_interrupt_parent(device_t dev)
+{
+ struct simplebus_devinfo *di;
+ struct fdt_ic *ic;
+ device_t ip;
+ phandle_t ph, iph;
+
+ ip = NULL;
+
+ di = device_get_ivars(dev);
+ if (di == NULL)
+ return (NULL);
+
+ if (OF_getencprop(di->di_ofw.obd_node, "interrupt-parent", &iph,
+ sizeof(iph)) > 0) {
+ ph = OF_xref_phandle(iph);
+ SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) {
+ if (ic->iph == ph) {
+ ip = ic->dev;
+ break;
+ }
+ }
+ }
+ return (ip);
+}
+
+static int
+simplebus_setup_intr(device_t bus, device_t child, struct resource *res,
+ int flags, driver_filter_t *filter, driver_intr_t *ihand, void *arg,
+ void **cookiep)
+{
+ struct simplebus_devinfo *di;
+ device_t ic;
+ enum intr_trigger trig;
+ enum intr_polarity pol;
+ int error, irq, rid;
+
+ di = device_get_ivars(child);
+ if (di == NULL)
+ return (ENXIO);
+
+ if (res == NULL)
+ return (EINVAL);
+
+ rid = rman_get_rid(res);
+ if (rid >= DI_MAX_INTR_NUM)
+ return (ENOENT);
+
+ ic = simplebus_get_interrupt_parent(child);
+
+ trig = di->di_intr_sl[rid].trig;
+ pol = di->di_intr_sl[rid].pol;
+ if (trig != INTR_TRIGGER_CONFORM || pol != INTR_POLARITY_CONFORM) {
+ irq = rman_get_start(res);
+ if (ic != NULL)
+ error = FDT_IC_CONFIG_INTR(ic, irq, trig, pol);
+ else
+ error = bus_generic_config_intr(bus, irq, trig, pol);
+ if (error)
+ return (error);
+ }
+
+ if (ic != NULL)
+ error = FDT_IC_SETUP_INTR(ic, child, res, flags, filter,
+ ihand, arg, cookiep);
+ else
+ error = bus_generic_setup_intr(bus, child, res, flags, filter,
+ ihand, arg, cookiep);
+ return (error);
+}
+
+static int
+simplebus_teardown_intr(device_t bus, device_t child, struct resource *res,
+ void *cookie)
+{
+ device_t ic;
+
+ if ((ic = simplebus_get_interrupt_parent(child)) != NULL)
+ return (FDT_IC_TEARDOWN_INTR(ic, child, res, cookie));
+
+ return (bus_generic_teardown_intr(bus, child, res, cookie));
+}
+
+static const struct ofw_bus_devinfo *
+simplebus_get_devinfo(device_t bus, device_t child)
+{
+ struct simplebus_devinfo *di;
+
+ di = device_get_ivars(child);
+ return (&di->di_ofw);
+}
diff --git a/sys/dev/fdt/fdt_ic_if.m b/sys/mips/beri/fdt_ic_if.m
index e11b8f8..e11b8f8 100644
--- a/sys/dev/fdt/fdt_ic_if.m
+++ b/sys/mips/beri/fdt_ic_if.m
diff --git a/sys/mips/beri/files.beri b/sys/mips/beri/files.beri
index 7bdcb31..de7ccc3 100644
--- a/sys/mips/beri/files.beri
+++ b/sys/mips/beri/files.beri
@@ -18,5 +18,7 @@ dev/terasic/mtl/terasic_mtl_syscons.c optional terasic_mtl
dev/terasic/mtl/terasic_mtl_text.c optional terasic_mtl
mips/beri/beri_machdep.c standard
mips/beri/beri_pic.c optional fdt
+mips/beri/beri_simplebus.c optional fdt
+mips/beri/fdt_ic_if.m optional fdt
mips/mips/intr_machdep.c standard
mips/mips/tick.c standard
diff --git a/sys/powerpc/ofw/ofw_pci.c b/sys/powerpc/ofw/ofw_pci.c
index 692b1ab..8543035 100644
--- a/sys/powerpc/ofw/ofw_pci.c
+++ b/sys/powerpc/ofw/ofw_pci.c
@@ -273,9 +273,7 @@ ofw_pci_route_interrupt(device_t bus, device_t dev, int pin)
&sc->sc_pci_iinfo, &reg, sizeof(reg), &pintr, sizeof(pintr),
mintr, sizeof(mintr), &iparent);
if (intrcells) {
- pintr = ofw_bus_map_intr(dev, iparent, mintr[0]);
- if (intrcells == 2)
- ofw_bus_config_intr(dev, pintr, mintr[1]);
+ pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr);
return (pintr);
}
diff --git a/sys/powerpc/ofw/ofw_pcib_pci.c b/sys/powerpc/ofw/ofw_pcib_pci.c
index df274c4..823f7c9 100644
--- a/sys/powerpc/ofw/ofw_pcib_pci.c
+++ b/sys/powerpc/ofw/ofw_pcib_pci.c
@@ -158,10 +158,8 @@ ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, int intpin)
* it again on higher levels - that causes problems
* in some cases, and never seems to be required.
*/
- mintr[0] = ofw_bus_map_intr(dev, iparent, mintr[0]);
- if (intrcells == 2)
- ofw_bus_config_intr(dev, mintr[0], mintr[1]);
-
+ mintr[0] = ofw_bus_map_intr(dev, iparent, intrcells,
+ mintr);
return (mintr[0]);
}
} else if (intpin >= 1 && intpin <= 4) {
diff --git a/sys/powerpc/ofw/ofw_pcibus.c b/sys/powerpc/ofw/ofw_pcibus.c
index f1063a1..ee14ccf 100644
--- a/sys/powerpc/ofw/ofw_pcibus.c
+++ b/sys/powerpc/ofw/ofw_pcibus.c
@@ -216,13 +216,9 @@ ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno)
"#interrupt-cells", &icells,
sizeof(icells));
intr[0] = ofw_bus_map_intr(dev, iparent,
- intr[0]);
+ icells, intr);
}
- if (iparent != 0 && icells > 1)
- ofw_bus_config_intr(dev, intr[0],
- intr[1]);
-
resource_list_add(&dinfo->opd_dinfo.resources,
SYS_RES_IRQ, 0, intr[0], intr[0], 1);
}
@@ -309,18 +305,18 @@ ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf,
static int
ofw_pcibus_assign_interrupt(device_t dev, device_t child)
{
- ofw_pci_intr_t intr;
+ ofw_pci_intr_t intr[2];
phandle_t node, iparent;
- int isz;
+ int isz, icells;
node = ofw_bus_get_node(child);
if (node == -1) {
/* Non-firmware enumerated child, use standard routing */
- intr = pci_get_intpin(child);
+ intr[0] = pci_get_intpin(child);
return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child,
- intr));
+ intr[0]));
}
/*
@@ -331,24 +327,28 @@ ofw_pcibus_assign_interrupt(device_t dev, device_t child)
iparent = -1;
if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) < 0)
iparent = -1;
+ icells = 1;
+ if (iparent != -1)
+ OF_getprop(OF_xref_phandle(iparent), "#interrupt-cells",
+ &icells, sizeof(icells));
/*
* Any AAPL,interrupts property gets priority and is
* fully specified (i.e. does not need routing)
*/
- isz = OF_getprop(node, "AAPL,interrupts", &intr, sizeof(intr));
- if (isz == sizeof(intr))
- return ((iparent == -1) ? intr : ofw_bus_map_intr(dev, iparent,
- intr));
+ isz = OF_getprop(node, "AAPL,interrupts", intr, sizeof(intr));
+ if (isz == sizeof(intr[0])*icells)
+ return ((iparent == -1) ? intr[0] : ofw_bus_map_intr(dev,
+ iparent, icells, intr));
- isz = OF_getprop(node, "interrupts", &intr, sizeof(intr));
- if (isz == sizeof(intr)) {
+ isz = OF_getprop(node, "interrupts", intr, sizeof(intr));
+ if (isz == sizeof(intr[0])*icells) {
if (iparent != -1)
- intr = ofw_bus_map_intr(dev, iparent, intr);
+ intr[0] = ofw_bus_map_intr(dev, iparent, icells, intr);
} else {
/* No property: our best guess is the intpin. */
- intr = pci_get_intpin(child);
+ intr[0] = pci_get_intpin(child);
}
/*
@@ -361,7 +361,7 @@ ofw_pcibus_assign_interrupt(device_t dev, device_t child)
* will always use the route_interrupt method, and treat exceptions
* on the level they become apparent.
*/
- return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr));
+ return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr[0]));
}
static const struct ofw_bus_devinfo *
diff --git a/sys/powerpc/powerpc/nexus.c b/sys/powerpc/powerpc/nexus.c
index f7100f1..2e9bbe6 100644
--- a/sys/powerpc/powerpc/nexus.c
+++ b/sys/powerpc/powerpc/nexus.c
@@ -75,7 +75,6 @@ static bus_bind_intr_t nexus_bind_intr;
#endif
static bus_config_intr_t nexus_config_intr;
static ofw_bus_map_intr_t nexus_ofw_map_intr;
-static ofw_bus_config_intr_t nexus_ofw_config_intr;
static device_method_t nexus_methods[] = {
/* Bus interface */
@@ -90,7 +89,6 @@ static device_method_t nexus_methods[] = {
/* ofw_bus interface */
DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr),
- DEVMETHOD(ofw_bus_config_intr, nexus_ofw_config_intr),
DEVMETHOD_END
};
@@ -157,19 +155,16 @@ nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
}
static int
-nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int irq)
+nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
+ pcell_t *irq)
{
- return (MAP_IRQ(iparent, irq));
+ u_int intr = MAP_IRQ(iparent, irq[0]);
+ if (icells > 1)
+ powerpc_fw_config_intr(intr, irq[1]);
+ return (intr);
}
static int
-nexus_ofw_config_intr(device_t dev, device_t child, int irq, int sense)
-{
-
- return (powerpc_fw_config_intr(irq, sense));
-}
-
-static int
nexus_activate_resource(device_t bus __unused, device_t child __unused,
int type, int rid __unused, struct resource *r)
{
diff --git a/sys/powerpc/pseries/vdevice.c b/sys/powerpc/pseries/vdevice.c
index 54cd5dd..e733a9d 100644
--- a/sys/powerpc/pseries/vdevice.c
+++ b/sys/powerpc/pseries/vdevice.c
@@ -157,7 +157,7 @@ vdevice_attach(device_t dev)
u_int irq = intr[i];
if (iparent != -1)
irq = ofw_bus_map_intr(dev, iparent,
- intr[i]);
+ icells, &intr[i]);
resource_list_add(&dinfo->mdi_resources,
SYS_RES_IRQ, i, irq, irq, i);
OpenPOWER on IntegriCloud