[PATCH rtems-libbsd 02/14] mpc85xx: Import from FreeBSD

Christian Mauderer christian.mauderer at embedded-brains.de
Tue Jan 23 09:09:03 UTC 2024


From: Sebastian Huber <sebastian.huber at embedded-brains.de>

---
 freebsd/sys/dev/ofw/ofwpci.c                  | 677 +++++++++++++
 freebsd/sys/dev/ofw/ofwpci.h                  |  87 ++
 freebsd/sys/dev/pci/pci_subr.c                | 388 +++++++
 freebsd/sys/powerpc/include/machine/hid.h     | 224 ++++
 freebsd/sys/powerpc/include/machine/pio.h     | 306 ++++++
 .../sys/powerpc/include/machine/platformvar.h |  91 ++
 freebsd/sys/powerpc/mpc85xx/mpc85xx.c         | 361 +++++++
 freebsd/sys/powerpc/mpc85xx/mpc85xx.h         | 177 ++++
 freebsd/sys/powerpc/mpc85xx/pci_mpc85xx.c     | 959 ++++++++++++++++++
 .../sys/powerpc/mpc85xx/pci_mpc85xx_pcib.c    | 111 ++
 .../sys/powerpc/mpc85xx/platform_mpc85xx.c    | 710 +++++++++++++
 freebsd/sys/powerpc/ofw/ofw_pcib_pci.c        | 178 ++++
 12 files changed, 4269 insertions(+)
 create mode 100644 freebsd/sys/dev/ofw/ofwpci.c
 create mode 100644 freebsd/sys/dev/ofw/ofwpci.h
 create mode 100644 freebsd/sys/dev/pci/pci_subr.c
 create mode 100644 freebsd/sys/powerpc/include/machine/hid.h
 create mode 100644 freebsd/sys/powerpc/include/machine/pio.h
 create mode 100644 freebsd/sys/powerpc/include/machine/platformvar.h
 create mode 100644 freebsd/sys/powerpc/mpc85xx/mpc85xx.c
 create mode 100644 freebsd/sys/powerpc/mpc85xx/mpc85xx.h
 create mode 100644 freebsd/sys/powerpc/mpc85xx/pci_mpc85xx.c
 create mode 100644 freebsd/sys/powerpc/mpc85xx/pci_mpc85xx_pcib.c
 create mode 100644 freebsd/sys/powerpc/mpc85xx/platform_mpc85xx.c
 create mode 100644 freebsd/sys/powerpc/ofw/ofw_pcib_pci.c

diff --git a/freebsd/sys/dev/ofw/ofwpci.c b/freebsd/sys/dev/ofw/ofwpci.c
new file mode 100644
index 00000000..d576cb67
--- /dev/null
+++ b/freebsd/sys/dev/ofw/ofwpci.c
@@ -0,0 +1,677 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofwpci.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+#include <machine/resource.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <rtems/bsd/local/pcib_if.h>
+
+/*
+ * If it is necessary to set another value of this for
+ * some platforms it should be set at fdt.h file
+ */
+#ifndef PCI_MAP_INTR
+#define	PCI_MAP_INTR	4
+#endif
+
+#define	PCI_INTR_PINS	4
+
+/*
+ * bus interface.
+ */
+static struct resource * ofw_pci_alloc_resource(device_t, device_t,
+    int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
+static int ofw_pci_release_resource(device_t, device_t, int, int,
+    struct resource *);
+static int ofw_pci_activate_resource(device_t, device_t, int, int,
+    struct resource *);
+static int ofw_pci_deactivate_resource(device_t, device_t, int, int,
+    struct resource *);
+static int ofw_pci_adjust_resource(device_t, device_t, int,
+    struct resource *, rman_res_t, rman_res_t);
+
+#ifdef __powerpc__
+static bus_space_tag_t ofw_pci_bus_get_bus_tag(device_t, device_t);
+#endif
+
+/*
+ * pcib interface
+ */
+static int ofw_pci_maxslots(device_t);
+
+/*
+ * ofw_bus interface
+ */
+static phandle_t ofw_pci_get_node(device_t, device_t);
+
+/*
+ * local methods
+ */
+static int ofw_pci_fill_ranges(phandle_t, struct ofw_pci_range *);
+static struct rman *ofw_pci_get_rman(struct ofw_pci_softc *, int, u_int);
+
+/*
+ * Driver methods.
+ */
+static device_method_t	ofw_pci_methods[] = {
+
+	/* Device interface */
+	DEVMETHOD(device_attach,	ofw_pci_attach),
+
+	/* Bus interface */
+	DEVMETHOD(bus_print_child,	bus_generic_print_child),
+	DEVMETHOD(bus_read_ivar,	ofw_pci_read_ivar),
+	DEVMETHOD(bus_write_ivar,	ofw_pci_write_ivar),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+	DEVMETHOD(bus_alloc_resource,	ofw_pci_alloc_resource),
+	DEVMETHOD(bus_release_resource,	ofw_pci_release_resource),
+	DEVMETHOD(bus_activate_resource,	ofw_pci_activate_resource),
+	DEVMETHOD(bus_deactivate_resource,	ofw_pci_deactivate_resource),
+	DEVMETHOD(bus_adjust_resource,	ofw_pci_adjust_resource),
+#ifdef __powerpc__
+	DEVMETHOD(bus_get_bus_tag,	ofw_pci_bus_get_bus_tag),
+#endif
+
+	/* pcib interface */
+	DEVMETHOD(pcib_maxslots,	ofw_pci_maxslots),
+	DEVMETHOD(pcib_route_interrupt,	ofw_pci_route_interrupt),
+	DEVMETHOD(pcib_request_feature,	pcib_request_feature_allow),
+
+	/* ofw_bus interface */
+	DEVMETHOD(ofw_bus_get_node,	ofw_pci_get_node),
+
+	DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(ofw_pci, ofw_pci_driver, ofw_pci_methods, 0);
+
+int
+ofw_pci_init(device_t dev)
+{
+	struct ofw_pci_softc *sc;
+	phandle_t node;
+	u_int32_t busrange[2];
+	struct ofw_pci_range *rp;
+	int i, error;
+	struct ofw_pci_cell_info *cell_info;
+
+	node = ofw_bus_get_node(dev);
+	sc = device_get_softc(dev);
+	sc->sc_initialized = 1;
+	sc->sc_range = NULL;
+	sc->sc_pci_domain = device_get_unit(dev);
+
+	cell_info = (struct ofw_pci_cell_info *)malloc(sizeof(*cell_info),
+	    M_DEVBUF, M_WAITOK | M_ZERO);
+
+	sc->sc_cell_info = cell_info;
+
+	if (OF_getencprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
+		busrange[0] = 0;
+
+	sc->sc_dev = dev;
+	sc->sc_node = node;
+	sc->sc_bus = busrange[0];
+
+	if (sc->sc_quirks & OFW_PCI_QUIRK_RANGES_ON_CHILDREN) {
+		phandle_t c;
+		int n, i;
+
+		sc->sc_nrange = 0;
+		for (c = OF_child(node); c != 0; c = OF_peer(c)) {
+			n = ofw_pci_nranges(c, cell_info);
+			if (n > 0)
+				sc->sc_nrange += n;
+		}
+		if (sc->sc_nrange == 0) {
+			error = ENXIO;
+			goto out;
+		}
+		sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]),
+		    M_DEVBUF, M_WAITOK);
+		i = 0;
+		for (c = OF_child(node); c != 0; c = OF_peer(c)) {
+			n = ofw_pci_fill_ranges(c, &sc->sc_range[i]);
+			if (n > 0)
+				i += n;
+		}
+		KASSERT(i == sc->sc_nrange, ("range count mismatch"));
+	} else {
+		sc->sc_nrange = ofw_pci_nranges(node, cell_info);
+		if (sc->sc_nrange <= 0) {
+			device_printf(dev, "could not getranges\n");
+			error = ENXIO;
+			goto out;
+		}
+		sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]),
+		    M_DEVBUF, M_WAITOK);
+		ofw_pci_fill_ranges(node, sc->sc_range);
+	}
+
+	sc->sc_io_rman.rm_type = RMAN_ARRAY;
+	sc->sc_io_rman.rm_descr = "PCI I/O Ports";
+	error = rman_init(&sc->sc_io_rman);
+	if (error != 0) {
+		device_printf(dev, "rman_init() failed. error = %d\n", error);
+		goto out;
+	}
+
+	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+	sc->sc_mem_rman.rm_descr = "PCI Non Prefetchable Memory";
+	error = rman_init(&sc->sc_mem_rman);
+	if (error != 0) {
+		device_printf(dev, "rman_init() failed. error = %d\n", error);
+		goto out;
+	}
+
+	sc->sc_pmem_rman.rm_type = RMAN_ARRAY;
+	sc->sc_pmem_rman.rm_descr = "PCI Prefetchable Memory";
+	error = rman_init(&sc->sc_pmem_rman);
+	if (error != 0) {
+		device_printf(dev, "rman_init() failed. error = %d\n", error);
+		goto out;
+	}
+
+	for (i = 0; i < sc->sc_nrange; i++) {
+		error = 0;
+		rp = sc->sc_range + i;
+
+		if (sc->sc_range_mask & ((uint64_t)1 << i))
+			continue;
+		switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+		case OFW_PCI_PHYS_HI_SPACE_CONFIG:
+			break;
+		case OFW_PCI_PHYS_HI_SPACE_IO:
+			error = rman_manage_region(&sc->sc_io_rman, rp->pci,
+			    rp->pci + rp->size - 1);
+			break;
+		case OFW_PCI_PHYS_HI_SPACE_MEM32:
+		case OFW_PCI_PHYS_HI_SPACE_MEM64:
+			if (rp->pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) {
+				sc->sc_have_pmem = 1;
+				error = rman_manage_region(&sc->sc_pmem_rman,
+				    rp->pci, rp->pci + rp->size - 1);
+			} else {
+				error = rman_manage_region(&sc->sc_mem_rman,
+				    rp->pci, rp->pci + rp->size - 1);
+			}
+			break;
+		}
+
+		if (error != 0) {
+			device_printf(dev,
+			    "rman_manage_region(%x, %#jx, %#jx) failed. "
+			    "error = %d\n", rp->pci_hi &
+			    OFW_PCI_PHYS_HI_SPACEMASK, rp->pci,
+			    rp->pci + rp->size - 1, error);
+			goto out;
+		}
+	}
+
+	ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
+	return (0);
+
+out:
+	free(cell_info, M_DEVBUF);
+	free(sc->sc_range, M_DEVBUF);
+	rman_fini(&sc->sc_io_rman);
+	rman_fini(&sc->sc_mem_rman);
+	rman_fini(&sc->sc_pmem_rman);
+
+	return (error);
+}
+
+int
+ofw_pci_attach(device_t dev)
+{
+	struct ofw_pci_softc *sc;
+	int error;
+
+	sc = device_get_softc(dev);
+	if (!sc->sc_initialized) {
+		error = ofw_pci_init(dev);
+		if (error != 0)
+			return (error);
+	}
+
+	device_add_child(dev, "pci", -1);
+	return (bus_generic_attach(dev));
+}
+
+static int
+ofw_pci_maxslots(device_t dev)
+{
+
+	return (PCI_SLOTMAX);
+}
+
+int
+ofw_pci_route_interrupt(device_t bus, device_t dev, int pin)
+{
+	struct ofw_pci_softc *sc;
+	struct ofw_pci_register reg;
+	uint32_t pintr, mintr[PCI_MAP_INTR];
+	int intrcells;
+	phandle_t iparent;
+
+	sc = device_get_softc(bus);
+	pintr = pin;
+
+	/* Fabricate imap information in case this isn't an OFW device */
+	bzero(&reg, sizeof(reg));
+	reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
+	    (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
+	    (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
+
+	intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev),
+	    &sc->sc_pci_iinfo, &reg, sizeof(reg), &pintr, sizeof(pintr),
+	    mintr, sizeof(mintr), &iparent);
+	if (intrcells != 0) {
+		pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr);
+		return (pintr);
+	}
+
+	/*
+	 * Maybe it's a real interrupt, not an intpin
+	 */
+	if (pin > PCI_INTR_PINS)
+		return (pin);
+
+	device_printf(bus, "could not route pin %d for device %d.%d\n",
+	    pin, pci_get_slot(dev), pci_get_function(dev));
+	return (PCI_INVALID_IRQ);
+}
+
+int
+ofw_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+	struct ofw_pci_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	switch (which) {
+	case PCIB_IVAR_DOMAIN:
+		*result = sc->sc_pci_domain;
+		return (0);
+	case PCIB_IVAR_BUS:
+		*result = sc->sc_bus;
+		return (0);
+	default:
+		break;
+	}
+
+	return (ENOENT);
+}
+
+int
+ofw_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+	struct ofw_pci_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	switch (which) {
+	case PCIB_IVAR_BUS:
+		sc->sc_bus = value;
+		return (0);
+	default:
+		break;
+	}
+
+	return (ENOENT);
+}
+
+int
+ofw_pci_nranges(phandle_t node, struct ofw_pci_cell_info *info)
+{
+	ssize_t nbase_ranges;
+
+	if (info == NULL)
+		return (-1);
+
+	info->host_address_cells = 1;
+	info->size_cells = 2;
+	info->pci_address_cell = 3;
+
+	OF_getencprop(OF_parent(node), "#address-cells",
+	    &(info->host_address_cells), sizeof(info->host_address_cells));
+	OF_getencprop(node, "#address-cells",
+	    &(info->pci_address_cell), sizeof(info->pci_address_cell));
+	OF_getencprop(node, "#size-cells", &(info->size_cells),
+	    sizeof(info->size_cells));
+
+	nbase_ranges = OF_getproplen(node, "ranges");
+	if (nbase_ranges <= 0)
+		return (-1);
+
+	return (nbase_ranges / sizeof(cell_t) /
+	    (info->pci_address_cell + info->host_address_cells +
+	    info->size_cells));
+}
+
+static struct resource *
+ofw_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
+	struct ofw_pci_softc *sc;
+	struct resource *rv;
+	struct rman *rm;
+	int needactivate;
+
+
+	needactivate = flags & RF_ACTIVE;
+	flags &= ~RF_ACTIVE;
+
+	sc = device_get_softc(bus);
+
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+	if (type ==  PCI_RES_BUS) {
+		  return (pci_domain_alloc_bus(sc->sc_pci_domain, child, rid,
+		      start, end, count, flags | needactivate));
+	}
+#endif
+
+	rm = ofw_pci_get_rman(sc, type, flags);
+	if (rm == NULL)  {
+		return (bus_generic_alloc_resource(bus, child, type, rid,
+		    start, end, count, flags | needactivate));
+	}
+
+	rv = rman_reserve_resource(rm, start, end, count, flags, child);
+	if (rv == NULL) {
+		device_printf(bus, "failed to reserve resource for %s\n",
+		    device_get_nameunit(child));
+		return (NULL);
+	}
+
+	rman_set_rid(rv, *rid);
+
+	if (needactivate) {
+		if (bus_activate_resource(child, type, *rid, rv) != 0) {
+			device_printf(bus,
+			    "failed to activate resource for %s\n",
+			    device_get_nameunit(child));
+			rman_release_resource(rv);
+			return (NULL);
+		}
+	}
+
+	return (rv);
+}
+
+static int
+ofw_pci_release_resource(device_t bus, device_t child, int type, int rid,
+    struct resource *res)
+{
+	struct ofw_pci_softc *sc;
+	struct rman *rm;
+	int error;
+
+	sc = device_get_softc(bus);
+
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+	if (type == PCI_RES_BUS)
+		return (pci_domain_release_bus(sc->sc_pci_domain, child, rid,
+		    res));
+#endif
+
+	rm = ofw_pci_get_rman(sc, type, rman_get_flags(res));
+	if (rm == NULL) {
+		return (bus_generic_release_resource(bus, child, type, rid,
+		    res));
+	}
+	KASSERT(rman_is_region_manager(res, rm), ("rman mismatch"));
+
+	if (rman_get_flags(res) & RF_ACTIVE) {
+		error = bus_deactivate_resource(child, type, rid, res);
+		if (error != 0)
+			return (error);
+	}
+	return (rman_release_resource(res));
+}
+
+static int
+ofw_pci_activate_resource(device_t bus, device_t child, int type, int rid,
+    struct resource *res)
+{
+	struct ofw_pci_softc *sc;
+	bus_space_handle_t handle;
+	bus_space_tag_t tag;
+	struct ofw_pci_range *rp;
+	vm_paddr_t start;
+	int space;
+	int rv;
+
+	sc = device_get_softc(bus);
+
+	if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY) {
+		return (bus_generic_activate_resource(bus, child, type, rid,
+		    res));
+	}
+
+	start = (vm_paddr_t)rman_get_start(res);
+
+	/*
+	 * Map this through the ranges list
+	 */
+	for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
+	    rp->pci_hi != 0; rp++) {
+		if (start < rp->pci || start >= rp->pci + rp->size)
+			continue;
+
+		switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+		case OFW_PCI_PHYS_HI_SPACE_IO:
+			space = SYS_RES_IOPORT;
+			break;
+		case OFW_PCI_PHYS_HI_SPACE_MEM32:
+		case OFW_PCI_PHYS_HI_SPACE_MEM64:
+			space = SYS_RES_MEMORY;
+			break;
+		default:
+			space = -1;
+			}
+
+		if (type == space) {
+			start += (rp->host - rp->pci);
+			break;
+		}
+	}
+
+	if (bootverbose)
+		printf("ofw_pci mapdev: start %jx, len %jd\n",
+		    (rman_res_t)start, rman_get_size(res));
+
+	tag = BUS_GET_BUS_TAG(child, child);
+	if (tag == NULL)
+		return (ENOMEM);
+
+	rman_set_bustag(res, tag);
+	rv = bus_space_map(tag, start,
+	    rman_get_size(res), 0, &handle);
+	if (rv != 0)
+		return (ENOMEM);
+
+	rman_set_bushandle(res, handle);
+	rman_set_virtual(res, (void *)handle); /* XXX  for powerpc only ? */
+
+	return (rman_activate_resource(res));
+}
+
+#ifdef __powerpc__
+static bus_space_tag_t
+ofw_pci_bus_get_bus_tag(device_t bus, device_t child)
+{
+
+	return (&bs_le_tag);
+}
+#endif
+
+static int
+ofw_pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
+    struct resource *res)
+{
+	vm_size_t psize;
+
+	if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY) {
+		return (bus_generic_deactivate_resource(bus, child, type, rid,
+		    res));
+	}
+
+	psize = rman_get_size(res);
+	pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize);
+
+	return (rman_deactivate_resource(res));
+}
+
+static int
+ofw_pci_adjust_resource(device_t bus, device_t child, int type,
+    struct resource *res, rman_res_t start, rman_res_t end)
+{
+	struct rman *rm;
+	struct ofw_pci_softc *sc;
+
+	sc = device_get_softc(bus);
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+	if (type == PCI_RES_BUS)
+		return (pci_domain_adjust_bus(sc->sc_pci_domain, child, res,
+		    start, end));
+#endif
+
+	rm = ofw_pci_get_rman(sc, type, rman_get_flags(res));
+	if (rm == NULL) {
+		return (bus_generic_adjust_resource(bus, child, type, res,
+		    start, end));
+	}
+	KASSERT(rman_is_region_manager(res, rm), ("rman mismatch"));
+	KASSERT(!(rman_get_flags(res) & RF_ACTIVE),
+	    ("active resources cannot be adjusted"));
+
+	return (rman_adjust_resource(res, start, end));
+}
+
+static phandle_t
+ofw_pci_get_node(device_t bus, device_t dev)
+{
+	struct ofw_pci_softc *sc;
+
+	sc = device_get_softc(bus);
+	/* We only have one child, the PCI bus, which needs our own node. */
+
+	return (sc->sc_node);
+}
+
+static int
+ofw_pci_fill_ranges(phandle_t node, struct ofw_pci_range *ranges)
+{
+	int host_address_cells = 1, pci_address_cells = 3, size_cells = 2;
+	cell_t *base_ranges;
+	ssize_t nbase_ranges;
+	int nranges;
+	int i, j, k;
+
+	OF_getencprop(OF_parent(node), "#address-cells", &host_address_cells,
+	    sizeof(host_address_cells));
+	OF_getencprop(node, "#address-cells", &pci_address_cells,
+	    sizeof(pci_address_cells));
+	OF_getencprop(node, "#size-cells", &size_cells, sizeof(size_cells));
+
+	nbase_ranges = OF_getproplen(node, "ranges");
+	if (nbase_ranges <= 0)
+		return (-1);
+	nranges = nbase_ranges / sizeof(cell_t) /
+	    (pci_address_cells + host_address_cells + size_cells);
+
+	base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
+	OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
+
+	for (i = 0, j = 0; i < nranges; i++) {
+		ranges[i].pci_hi = base_ranges[j++];
+		ranges[i].pci = 0;
+		for (k = 0; k < pci_address_cells - 1; k++) {
+			ranges[i].pci <<= 32;
+			ranges[i].pci |= base_ranges[j++];
+		}
+		ranges[i].host = 0;
+		for (k = 0; k < host_address_cells; k++) {
+			ranges[i].host <<= 32;
+			ranges[i].host |= base_ranges[j++];
+		}
+		ranges[i].size = 0;
+		for (k = 0; k < size_cells; k++) {
+			ranges[i].size <<= 32;
+			ranges[i].size |= base_ranges[j++];
+		}
+	}
+
+	free(base_ranges, M_DEVBUF);
+	return (nranges);
+}
+
+static struct rman *
+ofw_pci_get_rman(struct ofw_pci_softc *sc, int type, u_int flags)
+{
+
+	switch (type) {
+	case SYS_RES_IOPORT:
+		return (&sc->sc_io_rman);
+	case SYS_RES_MEMORY:
+		if (sc->sc_have_pmem  && (flags & RF_PREFETCHABLE))
+			return (&sc->sc_pmem_rman);
+		else
+			return (&sc->sc_mem_rman);
+	default:
+		break;
+	}
+
+	return (NULL);
+}
diff --git a/freebsd/sys/dev/ofw/ofwpci.h b/freebsd/sys/dev/ofw/ofwpci.h
new file mode 100644
index 00000000..3257fe68
--- /dev/null
+++ b/freebsd/sys/dev/ofw/ofwpci.h
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_OFW_OFWPCI_H_
+#define	_DEV_OFW_OFWPCI_H_
+
+/*
+ * Export class definition for inheritance purposes
+ */
+DECLARE_CLASS(ofw_pci_driver);
+
+struct ofw_pci_cell_info {
+	pcell_t host_address_cells;
+	pcell_t pci_address_cell;
+	pcell_t size_cells;
+ };
+
+struct ofw_pci_range {
+	uint32_t	pci_hi;
+	uint64_t	pci;
+	uint64_t	host;
+	uint64_t	size;
+};
+
+/*
+ * Quirks for some adapters
+ */
+enum {
+	OFW_PCI_QUIRK_RANGES_ON_CHILDREN = 1,
+};
+
+struct ofw_pci_softc {
+	device_t	sc_dev;
+	phandle_t	sc_node;
+	int		sc_bus;
+	int		sc_initialized;
+	int		sc_quirks;
+	int		sc_have_pmem;
+
+	struct ofw_pci_range		*sc_range;
+	int				sc_nrange;
+	uint64_t			sc_range_mask;
+	struct ofw_pci_cell_info	*sc_cell_info;
+
+	struct rman			sc_io_rman;
+	struct rman			sc_mem_rman;
+	struct rman			sc_pmem_rman;
+	bus_space_tag_t			sc_memt;
+	bus_dma_tag_t			sc_dmat;
+	int				sc_pci_domain;
+
+	struct ofw_bus_iinfo		sc_pci_iinfo;
+};
+
+int ofw_pci_init(device_t);
+int ofw_pci_attach(device_t);
+int ofw_pci_read_ivar(device_t, device_t, int, uintptr_t *);
+int ofw_pci_write_ivar(device_t, device_t, int, uintptr_t);
+int ofw_pci_route_interrupt(device_t, device_t, int);
+int ofw_pci_nranges(phandle_t, struct ofw_pci_cell_info *);
+
+#endif /* _DEV_OFW_OFWPCI_H_ */
diff --git a/freebsd/sys/dev/pci/pci_subr.c b/freebsd/sys/dev/pci/pci_subr.c
new file mode 100644
index 00000000..1b0fac29
--- /dev/null
+++ b/freebsd/sys/dev/pci/pci_subr.c
@@ -0,0 +1,388 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2011 Hudson River Trading LLC
+ * Written by: John H. Baldwin <jhb at FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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$");
+
+/*
+ * Support APIs for Host to PCI bridge drivers and drivers that
+ * provide PCI domains.
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcib_private.h>
+
+/*
+ * Try to read the bus number of a host-PCI bridge using appropriate config
+ * registers.
+ */
+int
+host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func,
+    uint8_t *busnum)
+{
+	uint32_t id;
+
+	id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4);
+	if (id == 0xffffffff)
+		return (0);
+
+	switch (id) {
+	case 0x12258086:
+		/* Intel 824?? */
+		/* XXX This is a guess */
+		/* *busnum = read_config(bus, slot, func, 0x41, 1); */
+		*busnum = bus;
+		break;
+	case 0x84c48086:
+		/* Intel 82454KX/GX (Orion) */
+		*busnum = read_config(bus, slot, func, 0x4a, 1);
+		break;
+	case 0x84ca8086:
+		/*
+		 * For the 450nx chipset, there is a whole bundle of
+		 * things pretending to be host bridges. The MIOC will 
+		 * be seen first and isn't really a pci bridge (the
+		 * actual buses are attached to the PXB's). We need to 
+		 * read the registers of the MIOC to figure out the
+		 * bus numbers for the PXB channels.
+		 *
+		 * Since the MIOC doesn't have a pci bus attached, we
+		 * pretend it wasn't there.
+		 */
+		return (0);
+	case 0x84cb8086:
+		switch (slot) {
+		case 0x12:
+			/* Intel 82454NX PXB#0, Bus#A */
+			*busnum = read_config(bus, 0x10, func, 0xd0, 1);
+			break;
+		case 0x13:
+			/* Intel 82454NX PXB#0, Bus#B */
+			*busnum = read_config(bus, 0x10, func, 0xd1, 1) + 1;
+			break;
+		case 0x14:
+			/* Intel 82454NX PXB#1, Bus#A */
+			*busnum = read_config(bus, 0x10, func, 0xd3, 1);
+			break;
+		case 0x15:
+			/* Intel 82454NX PXB#1, Bus#B */
+			*busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1;
+			break;
+		}
+		break;
+
+		/* ServerWorks -- vendor 0x1166 */
+	case 0x00051166:
+	case 0x00061166:
+	case 0x00081166:
+	case 0x00091166:
+	case 0x00101166:
+	case 0x00111166:
+	case 0x00171166:
+	case 0x01011166:
+	case 0x010f1014:
+	case 0x01101166:
+	case 0x02011166:
+	case 0x02251166:
+	case 0x03021014:
+		*busnum = read_config(bus, slot, func, 0x44, 1);
+		break;
+
+		/* Compaq/HP -- vendor 0x0e11 */
+	case 0x60100e11:
+		*busnum = read_config(bus, slot, func, 0xc8, 1);
+		break;
+	default:
+		/* Don't know how to read bus number. */
+		return 0;
+	}
+
+	return 1;
+}
+
+#ifdef NEW_PCIB
+/*
+ * Return a pointer to a pretty name for a PCI device.  If the device
+ * has a driver attached, the device's name is used, otherwise a name
+ * is generated from the device's PCI address.
+ */
+const char *
+pcib_child_name(device_t child)
+{
+	static char buf[64];
+
+	if (device_get_nameunit(child) != NULL)
+		return (device_get_nameunit(child));
+	snprintf(buf, sizeof(buf), "pci%d:%d:%d:%d", pci_get_domain(child),
+	    pci_get_bus(child), pci_get_slot(child), pci_get_function(child));
+	return (buf);
+}
+
+/*
+ * Some Host-PCI bridge drivers know which resource ranges they can
+ * decode and should only allocate subranges to child PCI devices.
+ * This API provides a way to manage this.  The bridge driver should
+ * initialize this structure during attach and call
+ * pcib_host_res_decodes() on each resource range it decodes.  It can
+ * then use pcib_host_res_alloc() and pcib_host_res_adjust() as helper
+ * routines for BUS_ALLOC_RESOURCE() and BUS_ADJUST_RESOURCE().  This
+ * API assumes that resources for any decoded ranges can be safely
+ * allocated from the parent via bus_generic_alloc_resource().
+ */
+int
+pcib_host_res_init(device_t pcib, struct pcib_host_resources *hr)
+{
+
+	hr->hr_pcib = pcib;
+	resource_list_init(&hr->hr_rl);
+	return (0);
+}
+
+int
+pcib_host_res_free(device_t pcib, struct pcib_host_resources *hr)
+{
+
+	resource_list_free(&hr->hr_rl);
+	return (0);
+}
+
+int
+pcib_host_res_decodes(struct pcib_host_resources *hr, int type, rman_res_t start,
+    rman_res_t end, u_int flags)
+{
+	struct resource_list_entry *rle;
+	int rid;
+
+	if (bootverbose)
+		device_printf(hr->hr_pcib, "decoding %d %srange %#jx-%#jx\n",
+		    type, flags & RF_PREFETCHABLE ? "prefetchable ": "", start,
+		    end);
+	rid = resource_list_add_next(&hr->hr_rl, type, start, end,
+	    end - start + 1);
+	if (flags & RF_PREFETCHABLE) {
+		KASSERT(type == SYS_RES_MEMORY,
+		    ("only memory is prefetchable"));
+		rle = resource_list_find(&hr->hr_rl, type, rid);
+		rle->flags = RLE_PREFETCH;
+	}
+	return (0);
+}
+
+struct resource *
+pcib_host_res_alloc(struct pcib_host_resources *hr, device_t dev, int type,
+    int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
+	struct resource_list_entry *rle;
+	struct resource *r;
+	rman_res_t new_start, new_end;
+
+	if (flags & RF_PREFETCHABLE)
+		KASSERT(type == SYS_RES_MEMORY,
+		    ("only memory is prefetchable"));
+
+	rle = resource_list_find(&hr->hr_rl, type, 0);
+	if (rle == NULL) {
+		/*
+		 * No decoding ranges for this resource type, just pass
+		 * the request up to the parent.
+		 */
+		return (bus_generic_alloc_resource(hr->hr_pcib, dev, type, rid,
+		    start, end, count, flags));
+	}
+
+restart:
+	/* Try to allocate from each decoded range. */
+	for (; rle != NULL; rle = STAILQ_NEXT(rle, link)) {
+		if (rle->type != type)
+			continue;
+		if (((flags & RF_PREFETCHABLE) != 0) !=
+		    ((rle->flags & RLE_PREFETCH) != 0))
+			continue;
+		new_start = ummax(start, rle->start);
+		new_end = ummin(end, rle->end);
+		if (new_start > new_end ||
+		    new_start + count - 1 > new_end ||
+		    new_start + count < new_start)
+			continue;
+		r = bus_generic_alloc_resource(hr->hr_pcib, dev, type, rid,
+		    new_start, new_end, count, flags);
+		if (r != NULL) {
+			if (bootverbose)
+				device_printf(hr->hr_pcib,
+			    "allocated type %d (%#jx-%#jx) for rid %x of %s\n",
+				    type, rman_get_start(r), rman_get_end(r),
+				    *rid, pcib_child_name(dev));
+			return (r);
+		}
+	}
+
+	/*
+	 * If we failed to find a prefetch range for a memory
+	 * resource, try again without prefetch.
+	 */
+	if (flags & RF_PREFETCHABLE) {
+		flags &= ~RF_PREFETCHABLE;
+		rle = resource_list_find(&hr->hr_rl, type, 0);
+		goto restart;
+	}
+	return (NULL);
+}
+
+int
+pcib_host_res_adjust(struct pcib_host_resources *hr, device_t dev, int type,
+    struct resource *r, rman_res_t start, rman_res_t end)
+{
+	struct resource_list_entry *rle;
+
+	rle = resource_list_find(&hr->hr_rl, type, 0);
+	if (rle == NULL) {
+		/*
+		 * No decoding ranges for this resource type, just pass
+		 * the request up to the parent.
+		 */
+		return (bus_generic_adjust_resource(hr->hr_pcib, dev, type, r,
+		    start, end));
+	}
+
+	/* Only allow adjustments that stay within a decoded range. */
+	for (; rle != NULL; rle = STAILQ_NEXT(rle, link)) {
+		if (rle->start <= start && rle->end >= end)
+			return (bus_generic_adjust_resource(hr->hr_pcib, dev,
+			    type, r, start, end));
+	}
+	return (ERANGE);
+}
+
+#ifdef PCI_RES_BUS
+struct pci_domain {
+	int	pd_domain;
+	struct rman pd_bus_rman;
+	TAILQ_ENTRY(pci_domain) pd_link;
+};
+
+static TAILQ_HEAD(, pci_domain) domains = TAILQ_HEAD_INITIALIZER(domains);
+
+/*
+ * Each PCI domain maintains its own resource manager for PCI bus
+ * numbers in that domain.  Domain objects are created on first use.
+ * Host to PCI bridge drivers and PCI-PCI bridge drivers should
+ * allocate their bus ranges from their domain.
+ */
+static struct pci_domain *
+pci_find_domain(int domain)
+{
+	struct pci_domain *d;
+	char buf[64];
+	int error;
+
+	TAILQ_FOREACH(d, &domains, pd_link) {
+		if (d->pd_domain == domain)
+			return (d);
+	}
+
+	snprintf(buf, sizeof(buf), "PCI domain %d bus numbers", domain);
+	d = malloc(sizeof(*d) + strlen(buf) + 1, M_DEVBUF, M_WAITOK | M_ZERO);
+	d->pd_domain = domain;
+	d->pd_bus_rman.rm_start = 0;
+	d->pd_bus_rman.rm_end = PCI_BUSMAX;
+	d->pd_bus_rman.rm_type = RMAN_ARRAY;
+	strcpy((char *)(d + 1), buf);
+	d->pd_bus_rman.rm_descr = (char *)(d + 1);
+	error = rman_init(&d->pd_bus_rman);
+	if (error == 0)
+		error = rman_manage_region(&d->pd_bus_rman, 0, PCI_BUSMAX);
+	if (error)
+		panic("Failed to initialize PCI domain %d rman", domain);
+	TAILQ_INSERT_TAIL(&domains, d, pd_link);
+	return (d);
+}
+
+struct resource *
+pci_domain_alloc_bus(int domain, device_t dev, int *rid, rman_res_t start,
+    rman_res_t end, rman_res_t count, u_int flags)
+{
+	struct pci_domain *d;
+	struct resource *res;
+
+	if (domain < 0 || domain > PCI_DOMAINMAX)
+		return (NULL);
+	d = pci_find_domain(domain);
+	res = rman_reserve_resource(&d->pd_bus_rman, start, end, count, flags,
+	    dev);
+	if (res == NULL)
+		return (NULL);
+
+	rman_set_rid(res, *rid);
+	return (res);
+}
+
+int
+pci_domain_adjust_bus(int domain, device_t dev, struct resource *r,
+    rman_res_t start, rman_res_t end)
+{
+#ifdef INVARIANTS
+	struct pci_domain *d;
+#endif
+
+	if (domain < 0 || domain > PCI_DOMAINMAX)
+		return (EINVAL);
+#ifdef INVARIANTS
+	d = pci_find_domain(domain);
+	KASSERT(rman_is_region_manager(r, &d->pd_bus_rman), ("bad resource"));
+#endif
+	return (rman_adjust_resource(r, start, end));
+}
+
+int
+pci_domain_release_bus(int domain, device_t dev, int rid, struct resource *r)
+{
+#ifdef INVARIANTS
+	struct pci_domain *d;
+#endif
+
+	if (domain < 0 || domain > PCI_DOMAINMAX)
+		return (EINVAL);
+#ifdef INVARIANTS
+	d = pci_find_domain(domain);
+	KASSERT(rman_is_region_manager(r, &d->pd_bus_rman), ("bad resource"));
+#endif
+	return (rman_release_resource(r));
+}
+#endif /* PCI_RES_BUS */
+
+#endif /* NEW_PCIB */
diff --git a/freebsd/sys/powerpc/include/machine/hid.h b/freebsd/sys/powerpc/include/machine/hid.h
new file mode 100644
index 00000000..1b038111
--- /dev/null
+++ b/freebsd/sys/powerpc/include/machine/hid.h
@@ -0,0 +1,224 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2000 Tsubai Masanari.  All rights reserved.
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ * $NetBSD: hid.h,v 1.2 2001/08/22 21:05:25 matt Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _POWERPC_HID_H_
+#define _POWERPC_HID_H_
+
+/* Hardware Implementation Dependent registers for the PowerPC */
+#define	HID0_RADIX	0x0080000000000000	/* Enable Radix page tables (POWER9) */
+
+#define HID0_EMCP	0x80000000  /* Enable machine check pin */
+#define HID0_DBP	0x40000000  /* Disable 60x bus parity generation */
+#define HID0_EBA	0x20000000  /* Enable 60x bus address parity checking */
+#define HID0_EBD	0x10000000  /* Enable 60x bus data parity checking */
+#define HID0_BCLK	0x08000000  /* CLK_OUT clock type selection */
+#define HID0_EICE	0x04000000  /* Enable ICE output */
+#define HID0_ECLK	0x02000000  /* CLK_OUT clock type selection */
+#define HID0_PAR	0x01000000  /* Disable precharge of ARTRY */
+#define HID0_STEN	0x01000000  /* Software table search enable (7450) */
+#define HID0_DEEPNAP	0x01000000  /* Enable deep nap mode (970) */
+#define HID0_HBATEN	0x00800000  /* High BAT enable (74[45][578])  */
+#define HID0_DOZE	0x00800000  /* Enable doze mode */
+#define HID0_NAP	0x00400000  /* Enable nap mode */
+#define HID0_SLEEP	0x00200000  /* Enable sleep mode */
+#define HID0_DPM	0x00100000  /* Enable Dynamic power management */
+#define HID0_RISEG	0x00080000  /* Read I-SEG */
+#define HID0_TG		0x00040000  /* Timebase Granularity (OEA64) */
+#define HID0_BHTCLR	0x00040000  /* Clear branch history table (7450) */
+#define HID0_EIEC	0x00040000  /* Enable internal error checking */
+#define HID0_XAEN	0x00020000  /* Enable eXtended Addressing (7450) */
+#define HID0_NHR	0x00010000  /* Not hard reset */
+#define HID0_ICE	0x00008000  /* Enable i-cache */
+#define HID0_DCE	0x00004000  /* Enable d-cache */
+#define HID0_ILOCK	0x00002000  /* i-cache lock */
+#define HID0_DLOCK	0x00001000  /* d-cache lock */
+#define HID0_ICFI	0x00000800  /* i-cache flush invalidate */
+#define HID0_DCFI	0x00000400  /* d-cache flush invalidate */
+#define HID0_SPD	0x00000200  /* Disable speculative cache access */
+#define HID0_XBSEN	0x00000100  /* Extended BAT block-size enable (7457) */
+#define HID0_IFEM	0x00000100  /* Enable M-bit for I-fetch */
+#define HID0_XBSEN	0x00000100  /* Extended BAT block size enable (7455+)*/
+#define HID0_SGE	0x00000080  /* Enable store gathering */
+#define HID0_DCFA	0x00000040  /* Data cache flush assist */
+#define HID0_BTIC	0x00000020  /* Enable BTIC */
+#define HID0_LRSTK	0x00000010  /* Link register stack enable (7450) */
+#define HID0_ABE	0x00000008  /* Enable address broadcast */
+#define HID0_FOLD	0x00000008  /* Branch folding enable (7450) */
+#define HID0_BHT	0x00000004  /* Enable branch history table */
+#define HID0_NOPTI	0x00000001  /* No-op the dcbt(st) */
+
+#define HID0_AIM_TBEN	0x04000000  /* Time base enable (7450) */
+
+#define HID0_E500_TBEN		0x00004000 /* Time Base and decr. enable */
+#define HID0_E500_SEL_TBCLK	0x00002000 /* Select Time Base clock */
+#define HID0_E500_MAS7UPDEN	0x00000080 /* Enable MAS7 update (e500v2) */
+
+#define HID0_E500MC_L2MMU_MHD	0x40000000 /* L2MMU Multiple Hit Detection */
+
+#define HID0_BITMASK							\
+    "\20"								\
+    "\040EMCP\037DBP\036EBA\035EBD\034BCLK\033EICE\032ECLK\031PAR"	\
+    "\030DOZE\027NAP\026SLEEP\025DPM\024RISEG\023EIEC\022res\021NHR"	\
+    "\020ICE\017DCE\016ILOCK\015DLOCK\014ICFI\013DCFI\012SPD\011IFEM"	\
+    "\010SGE\007DCFA\006BTIC\005FBIOB\004ABE\003BHT\002NOPDST\001NOPTI"
+
+#define HID0_7450_BITMASK						\
+    "\20"								\
+    "\040EMCP\037b1\036b2\035b3\034b4\033TBEN\032b6\031STEN"		\
+    "\030HBATEN\027NAP\026SLEEP\025DPM\024b12\023BHTCLR\022XAEN\021NHR"	\
+    "\020ICE\017DCE\016ILOCK\015DLOCK\014ICFI\013DCFI\012SPD\011XBSEN"	\
+    "\010SGE\007b25\006BTIC\005LRSTK\004FOLD\003BHT\002NOPDST\001NOPTI"
+
+#define HID0_E500_BITMASK						\
+    "\20"								\
+    "\040EMCP\037b1\036b2\035b3\034b4\033b5\032b6\031b7"		\
+    "\030DOZE\027NAP\026SLEEP\025b11\024b12\023b13\022b14\021b15"	\
+    "\020b16\017TBEN\016SEL_TBCLK\015b19\014b20\013b21\012b22\011b23"	\
+    "\010EN_MAS7_UPDATE\007DCFA\006b26\005b27\004b28\003b29\002b30\001NOPTI"
+
+#define HID0_970_BITMASK						\
+    "\20"								\
+    "\040ONEPPC\037SINGLE\036ISYNCSC\035SERGP\031DEEPNAP\030DOZE"	\
+    "\027NAP\025DPM\023TG\022HANGDETECT\021NHR\020INORDER"		\
+    "\016TBCTRL\015TBEN\012CIABREN\011HDICEEN\001ENATTN"		
+
+#define HID0_E500MC_BITMASK						\
+    "\20"								\
+    "\040EMCP\037EN_L2MMU_MHD\036b2\035b3\034b4\033b5\032b6\031b7"	\
+    "\030b8\027b9\026b10\025b11\024b12\023b13\022b14\021b15"		\
+    "\020b16\017b17\016b18\015b19\014b20\013b21\012b22\011b23"		\
+    "\010EN_MAS7_UPDATE\007DCFA\006b26\005CIGLSO\004b28\003b29\002b30\001NOPTI"
+
+#define HID0_E5500_BITMASK						\
+    "\20"								\
+    "\040EMCP\037EN_L2MMU_MHD\036b2\035b3\034b4\033b5\032b6\031b7"	\
+    "\030b8\027b9\026b10\025b11\024b12\023b13\022b14\021b15"		\
+    "\020b16\017b17\016b18\015b19\014b20\013b21\012b22\011b23"		\
+    "\010b24\007DCFA\006b26\005CIGLSO\004b28\003b29\002b30\001NOPTI"
+
+/*
+ *  HID0 bit definitions per cpu model
+ *
+ * bit	603	604	750	7400	7410	7450	7457	e500
+ *   0	EMCP	EMCP	EMCP	EMCP	EMCP	-	-	EMCP
+ *   1	-	ECP	DBP	-	-	-	-	-
+ *   2	EBA	EBA	EBA	EBA	EDA	-	-	-
+ *   3	EBD	EBD	EBD	EBD	EBD	-	-	-
+ *   4	SBCLK	-	BCLK	BCKL	BCLK	-	-	-
+ *   5	EICE	-	-	-	-	TBEN	TBEN	-
+ *   6	ECLK	-	ECLK	ECLK	ECLK	-	-	-
+ *   7	PAR	PAR	PAR	PAR	PAR	STEN	STEN	-
+ *   8	DOZE	-	DOZE	DOZE	DOZE	-	HBATEN	DOZE
+ *   9	NAP	-	NAP	NAP	NAP	NAP	NAP	NAP
+ *  10	SLEEP	-	SLEEP	SLEEP	SLEEP	SLEEP	SLEEP	SLEEP
+ *  11	DPM	-	DPM	DPM	DPM	DPM	DPM	-
+ *  12	RISEG	-	-	RISEG	-	-	-	-
+ *  13	-	-	-	EIEC	EIEC	BHTCLR	BHTCLR	-
+ *  14	-	-	-	-	-	XAEN	XAEN	-
+ *  15	-	NHR	NHR	NHR	NHR	NHR	NHR	-
+ *  16	ICE	ICE	ICE	ICE	ICE	ICE	ICE	-
+ *  17	DCE	DCE	DCE	DCE	DCE	DCE	DCE	TBEN
+ *  18	ILOCK	ILOCK	ILOCK	ILOCK	ILOCK	ILOCK	ILOCK	SEL_TBCLK
+ *  19	DLOCK	DLOCK	DLOCK	DLOCK	DLOCK	DLOCK	DLOCK	-
+ *  20	ICFI	ICFI	ICFI	ICFI	ICFI	ICFI	ICFI	-
+ *  21	DCFI	DCFI	DCFI	DCFI	DCFI	DCFI	DCFI	-
+ *  22	-	-	SPD	SPD	SPG	SPD	SPD	-
+ *  23	-	-	IFEM	IFTT	IFTT	-	XBSEN	-
+ *  24	-	SIE	SGE	SGE	SGE	SGE	SGE	EN_MAS7_UPDATE
+ *  25	-	-	DCFA	DCFA	DCFA	-	-	DCFA
+ *  26	-	-	BTIC	BTIC	BTIC	BTIC	BTIC	-
+ *  27	FBIOB	-	-	-	-	LRSTK	LRSTK	-
+ *  28	-	-	ABE	-	-	FOLD	FOLD	-
+ *  29	-	BHT	BHT	BHT	BHT	BHT	BHT	-
+ *  30	-	-	-	NOPDST	NOPDST	NOPDST	NOPDST	-
+ *  31	NOOPTI	-	NOOPTI	NOPTI	NOPTI	NOPTI	NOPTI	NOPTI
+ *
+ * bit	e500mc		e5500
+ *   0	EMCP		EMCP
+ *   1	EN_L2MMU_MHD	EN_L2MMU_MHD
+ *   2	-		-
+ *   3	-		-
+ *   4	-		-
+ *   5	-		-
+ *   6	-		-
+ *   7	-		-
+ *   8	-		-
+ *   9	-		-
+ *  10	-		-
+ *  11	-		-
+ *  12	-		-
+ *  13	-		-
+ *  14	-		-
+ *  15	-		-
+ *  16	-		-
+ *  17	-		-
+ *  18	-		-
+ *  19	-		-
+ *  20	-		-
+ *  21	-		-
+ *  22	-		-
+ *  23	-		-
+ *  24	EN_MAS7_UPDATE	-
+ *  25	DCFA		DCFA
+ *  26	-		-
+ *  27	CIGLSO		CIGLSO
+ *  28	-		-
+ *  29	-		-
+ *  30	-		-
+ *  31	NOPTI		NOPTI
+ *
+ *  604: ECP = Enable cache parity checking
+ *  604: SIE = Serial instruction execution disable
+ * 7450: TBEN = Time Base Enable
+ * 7450: STEN = Software table lookup enable
+ * 7450: BHTCLR = Branch history clear
+ * 7450: XAEN = Extended Addressing Enabled
+ * 7450: LRSTK = Link Register Stack Enable
+ * 7450: FOLD = Branch folding enable
+ * 7457: HBATEN = High BAT Enable
+ * 7457: XBSEN = Extended BAT Block Size Enable
+ */
+
+#define HID1_E500_ABE	0x00001000  /* Address broadcast enable */
+#define HID1_E500_ASTME	0x00002000  /* Address bus streaming mode enable */
+#define HID1_E500_RFXE	0x00020000  /* Read fault exception enable */
+
+#define HID0_E500_DEFAULT_SET	(HID0_EMCP | HID0_E500_TBEN | \
+				 HID0_E500_MAS7UPDEN)
+#define HID1_E500_DEFAULT_SET	(HID1_E500_ABE | HID1_E500_ASTME)
+#define HID0_E500MC_DEFAULT_SET	(HID0_EMCP | HID0_E500MC_L2MMU_MHD | \
+				 HID0_E500_MAS7UPDEN)
+#define HID0_E5500_DEFAULT_SET	(HID0_EMCP | HID0_E500MC_L2MMU_MHD)
+
+#define HID5_970_DCBZ_SIZE_HI	0x00000080UL	/* dcbz does a 32-byte store */
+#define HID4_970_DISABLE_LG_PG	0x00000004ULL	/* disables large pages */
+
+#endif /* _POWERPC_HID_H_ */
diff --git a/freebsd/sys/powerpc/include/machine/pio.h b/freebsd/sys/powerpc/include/machine/pio.h
new file mode 100644
index 00000000..a4d9b327
--- /dev/null
+++ b/freebsd/sys/powerpc/include/machine/pio.h
@@ -0,0 +1,306 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1997 Per Fogelstrom, Opsycon AB and RTMX Inc, USA.
+ * 
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed under OpenBSD by
+ *	Per Fogelstrom Opsycon AB for RTMX Inc, North Carolina, USA.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ *	$NetBSD: pio.h,v 1.1 1998/05/15 10:15:54 tsubai Exp $
+ *	$OpenBSD: pio.h,v 1.1 1997/10/13 10:53:47 pefo Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_PIO_H_
+#define	_MACHINE_PIO_H_
+/*
+ * I/O macros.
+ */
+
+/*
+ * Use sync so that bus space operations cannot sneak out the bottom of
+ * mutex-protected sections (mutex release does not guarantee completion of
+ * accesses to caching-inhibited memory on some systems)
+ */
+#define powerpc_iomb() __asm __volatile("sync" : : : "memory")
+
+static __inline void
+__outb(volatile u_int8_t *a, u_int8_t v)
+{
+	*a = v;
+	powerpc_iomb();
+}
+
+static __inline void
+__outw(volatile u_int16_t *a, u_int16_t v)
+{
+	*a = v;
+	powerpc_iomb();
+}
+
+static __inline void
+__outl(volatile u_int32_t *a, u_int32_t v)
+{
+	*a = v;
+	powerpc_iomb();
+}
+
+static __inline void
+__outll(volatile u_int64_t *a, u_int64_t v)
+{
+	*a = v;
+	powerpc_iomb();
+}
+
+static __inline void
+__outwrb(volatile u_int16_t *a, u_int16_t v)
+{
+	__asm__ volatile("sthbrx %0, 0, %1" :: "r"(v), "r"(a));
+	powerpc_iomb();
+}
+
+static __inline void
+__outlrb(volatile u_int32_t *a, u_int32_t v)
+{
+	__asm__ volatile("stwbrx %0, 0, %1" :: "r"(v), "r"(a));
+	powerpc_iomb();
+}
+
+static __inline u_int8_t
+__inb(volatile u_int8_t *a)
+{
+	u_int8_t _v_;
+
+	_v_ = *a;
+	powerpc_iomb();
+	return _v_;
+}
+
+static __inline u_int16_t
+__inw(volatile u_int16_t *a)
+{
+	u_int16_t _v_;
+
+	_v_ = *a;
+	powerpc_iomb();
+	return _v_;
+}
+
+static __inline u_int32_t
+__inl(volatile u_int32_t *a)
+{
+	u_int32_t _v_;
+
+	_v_ = *a;
+	powerpc_iomb();
+	return _v_;
+}
+
+static __inline u_int64_t
+__inll(volatile u_int64_t *a)
+{
+	u_int64_t _v_;
+
+	_v_ = *a;
+	powerpc_iomb();
+	return _v_;
+}
+
+static __inline u_int16_t
+__inwrb(volatile u_int16_t *a)
+{
+	u_int16_t _v_;
+
+	__asm__ volatile("lhbrx %0, 0, %1" : "=r"(_v_) : "r"(a));
+	powerpc_iomb();
+	return _v_;
+}
+
+static __inline u_int32_t
+__inlrb(volatile u_int32_t *a)
+{
+	u_int32_t _v_;
+
+	__asm__ volatile("lwbrx %0, 0, %1" : "=r"(_v_) : "r"(a));
+	powerpc_iomb();
+	return _v_;
+}
+
+#define	outb(a,v)	(__outb((volatile u_int8_t *)(a), v))
+#define	out8(a,v)	outb(a,v)
+#define	outw(a,v)	(__outw((volatile u_int16_t *)(a), v))
+#define	out16(a,v)	outw(a,v)
+#define	outl(a,v)	(__outl((volatile u_int32_t *)(a), v))
+#define	out32(a,v)	outl(a,v)
+#define	outll(a,v)	(__outll((volatile u_int64_t *)(a), v))
+#define	out64(a,v)	outll(a,v)
+#define	inb(a)		(__inb((volatile u_int8_t *)(a)))
+#define	in8(a)		inb(a)
+#define	inw(a)		(__inw((volatile u_int16_t *)(a)))
+#define	in16(a)		inw(a)
+#define	inl(a)		(__inl((volatile u_int32_t *)(a)))
+#define	in32(a)		inl(a)
+#define	inll(a)		(__inll((volatile u_int64_t *)(a)))
+#define	in64(a)		inll(a)
+
+#define	out8rb(a,v)	outb(a,v)
+#define	outwrb(a,v)	(__outwrb((volatile u_int16_t *)(a), v))
+#define	out16rb(a,v)	outwrb(a,v)
+#define	outlrb(a,v)	(__outlrb((volatile u_int32_t *)(a), v))
+#define	out32rb(a,v)	outlrb(a,v)
+#define	in8rb(a)	inb(a)
+#define	inwrb(a)	(__inwrb((volatile u_int16_t *)(a)))
+#define	in16rb(a)	inwrb(a)
+#define	inlrb(a)	(__inlrb((volatile u_int32_t *)(a)))
+#define	in32rb(a)	inlrb(a)
+
+
+static __inline void
+__outsb(volatile u_int8_t *a, const u_int8_t *s, size_t c)
+{
+	while (c--)
+		*a = *s++;
+	powerpc_iomb();
+}
+
+static __inline void
+__outsw(volatile u_int16_t *a, const u_int16_t *s, size_t c)
+{
+	while (c--)
+		*a = *s++;
+	powerpc_iomb();
+}
+
+static __inline void
+__outsl(volatile u_int32_t *a, const u_int32_t *s, size_t c)
+{
+	while (c--)
+		*a = *s++;
+	powerpc_iomb();
+}
+
+static __inline void
+__outsll(volatile u_int64_t *a, const u_int64_t *s, size_t c)
+{
+	while (c--)
+		*a = *s++;
+	powerpc_iomb();
+}
+
+static __inline void
+__outswrb(volatile u_int16_t *a, const u_int16_t *s, size_t c)
+{
+	while (c--)
+		__asm__ volatile("sthbrx %0, 0, %1" :: "r"(*s++), "r"(a));
+	powerpc_iomb();
+}
+
+static __inline void
+__outslrb(volatile u_int32_t *a, const u_int32_t *s, size_t c)
+{
+	while (c--)
+		__asm__ volatile("stwbrx %0, 0, %1" :: "r"(*s++), "r"(a));
+	powerpc_iomb();
+}
+
+static __inline void
+__insb(volatile u_int8_t *a, u_int8_t *d, size_t c)
+{
+	while (c--)
+		*d++ = *a;
+	powerpc_iomb();
+}
+
+static __inline void
+__insw(volatile u_int16_t *a, u_int16_t *d, size_t c)
+{
+	while (c--)
+		*d++ = *a;
+	powerpc_iomb();
+}
+
+static __inline void
+__insl(volatile u_int32_t *a, u_int32_t *d, size_t c)
+{
+	while (c--)
+		*d++ = *a;
+	powerpc_iomb();
+}
+
+static __inline void
+__insll(volatile u_int64_t *a, u_int64_t *d, size_t c)
+{
+	while (c--)
+		*d++ = *a;
+	powerpc_iomb();
+}
+
+static __inline void
+__inswrb(volatile u_int16_t *a, u_int16_t *d, size_t c)
+{
+	while (c--)
+		__asm__ volatile("lhbrx %0, 0, %1" : "=r"(*d++) : "r"(a));
+	powerpc_iomb();
+}
+
+static __inline void
+__inslrb(volatile u_int32_t *a, u_int32_t *d, size_t c)
+{
+	while (c--)
+		__asm__ volatile("lwbrx %0, 0, %1" : "=r"(*d++) : "r"(a));
+	powerpc_iomb();
+}
+
+#define	outsb(a,s,c)	(__outsb((volatile u_int8_t *)(a), s, c))
+#define	outs8(a,s,c)	outsb(a,s,c)
+#define	outsw(a,s,c)	(__outsw((volatile u_int16_t *)(a), s, c))
+#define	outs16(a,s,c)	outsw(a,s,c)
+#define	outsl(a,s,c)	(__outsl((volatile u_int32_t *)(a), s, c))
+#define	outs32(a,s,c)	outsl(a,s,c)
+#define	outsll(a,s,c)	(__outsll((volatile u_int64_t *)(a), s, c))
+#define	outs64(a,s,c)	outsll(a,s,c)
+#define	insb(a,d,c)	(__insb((volatile u_int8_t *)(a), d, c))
+#define	ins8(a,d,c)	insb(a,d,c)
+#define	insw(a,d,c)	(__insw((volatile u_int16_t *)(a), d, c))
+#define	ins16(a,d,c)	insw(a,d,c)
+#define	insl(a,d,c)	(__insl((volatile u_int32_t *)(a), d, c))
+#define	ins32(a,d,c)	insl(a,d,c)
+#define	insll(a,d,c)	(__insll((volatile u_int64_t *)(a), d, c))
+#define	ins64(a,d,c)	insll(a,d,c)
+
+#define	outs8rb(a,s,c)	outsb(a,s,c)
+#define	outswrb(a,s,c)	(__outswrb((volatile u_int16_t *)(a), s, c))
+#define	outs16rb(a,s,c)	outswrb(a,s,c)
+#define	outslrb(a,s,c)	(__outslrb((volatile u_int32_t *)(a), s, c))
+#define	outs32rb(a,s,c)	outslrb(a,s,c)
+#define	ins8rb(a,d,c)	insb(a,d,c)
+#define	inswrb(a,d,c)	(__inswrb((volatile u_int16_t *)(a), d, c))
+#define	ins16rb(a,d,c)	inswrb(a,d,c)
+#define	inslrb(a,d,c)	(__inslrb((volatile u_int32_t *)(a), d, c))
+#define	ins32rb(a,d,c)	inslrb(a,d,c)
+
+#endif /*_MACHINE_PIO_H_*/
diff --git a/freebsd/sys/powerpc/include/machine/platformvar.h b/freebsd/sys/powerpc/include/machine/platformvar.h
new file mode 100644
index 00000000..d5928e72
--- /dev/null
+++ b/freebsd/sys/powerpc/include/machine/platformvar.h
@@ -0,0 +1,91 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2005 Peter Grehan
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_PLATFORMVAR_H_
+#define _MACHINE_PLATFORMVAR_H_
+
+/*
+ * A PowerPC platform implementation is declared with a kernel object and
+ * an associated method table, similar to a device driver.
+ *
+ * e.g.
+ *
+ * static platform_method_t chrp_methods[] = {
+ *	PLATFORMMETHOD(platform_probe,		chrp_probe),
+ *	PLATFORMMETHOD(platform_mem_regions,	ofw_mem_regions),
+ *  ...
+ *	PLATFORMMETHOD(platform_smp_first_cpu,	chrp_smp_first_cpu),
+ *	{ 0, 0 }
+ * };
+ *
+ * static platform_def_t chrp_platform = {
+ * 	"chrp",
+ *	chrp_methods,
+ *	sizeof(chrp_platform_softc),	// or 0 if no softc
+ * };
+ *
+ * PLATFORM_DEF(chrp_platform);
+ */
+
+#include <sys/kobj.h>
+
+struct platform_kobj {
+	/*
+	 * A platform instance is a kernel object
+	 */
+	KOBJ_FIELDS;
+
+	/*
+	 * Utility elements that an instance may use
+	 */
+	struct mtx	platform_mtx;	/* available for instance use */
+	void		*platform_iptr;	/* instance data pointer */
+
+	/*
+	 * Opaque data that can be overlaid with an instance-private
+	 * structure. Platform code can test that this is large enough at
+	 * compile time with a sizeof() test againt it's softc. There
+	 * is also a run-time test when the platform kernel object is
+	 * registered.
+	 */
+#define PLATFORM_OPAQUESZ	64
+	u_int		platform_opaque[PLATFORM_OPAQUESZ];
+};
+
+typedef struct platform_kobj	*platform_t;
+typedef struct kobj_class	platform_def_t;
+#define platform_method_t	kobj_method_t
+
+#define PLATFORMMETHOD		KOBJMETHOD
+#define	PLATFORMMETHOD_END	KOBJMETHOD_END
+
+#define PLATFORM_DEF(name)	DATA_SET(platform_set, name)
+
+#endif /* _MACHINE_PLATFORMVAR_H_ */
diff --git a/freebsd/sys/powerpc/mpc85xx/mpc85xx.c b/freebsd/sys/powerpc/mpc85xx/mpc85xx.c
new file mode 100644
index 00000000..4c4b4c2f
--- /dev/null
+++ b/freebsd/sys/powerpc/mpc85xx/mpc85xx.c
@@ -0,0 +1,361 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (C) 2008 Semihalf, Rafal Jaworowski
+ * All rights reserved.
+ *
+ * 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 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 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 <rtems/bsd/local/opt_platform.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/reboot.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#ifndef __rtems__
+#include <machine/machdep.h>
+#endif /* __rtems__ */
+#include <machine/pio.h>
+#include <machine/spr.h>
+
+#include <dev/fdt/fdt_common.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+
+/*
+ * MPC85xx system specific routines
+ */
+
+uint32_t
+ccsr_read4(uintptr_t addr)
+{
+	volatile uint32_t *ptr = (void *)addr;
+
+	return (*ptr);
+}
+
+void
+ccsr_write4(uintptr_t addr, uint32_t val)
+{
+	volatile uint32_t *ptr = (void *)addr;
+
+	*ptr = val;
+	powerpc_iomb();
+}
+
+int
+law_getmax(void)
+{
+	uint32_t ver;
+	int law_max;
+
+	ver = SVR_VER(mfspr(SPR_SVR));
+	switch (ver) {
+	case SVR_MPC8555:
+	case SVR_MPC8555E:
+		law_max = 8;
+		break;
+	case SVR_MPC8533:
+	case SVR_MPC8533E:
+	case SVR_MPC8548:
+	case SVR_MPC8548E:
+		law_max = 10;
+		break;
+	case SVR_P5020:
+	case SVR_P5020E:
+	case SVR_P5021:
+	case SVR_P5021E:
+	case SVR_P5040:
+	case SVR_P5040E:
+		law_max = 32;
+		break;
+	default:
+		law_max = 8;
+	}
+
+	return (law_max);
+}
+
+static inline void
+law_write(uint32_t n, uint64_t bar, uint32_t sr)
+{
+
+	if (mpc85xx_is_qoriq()) {
+		ccsr_write4(OCP85XX_LAWBARH(n), bar >> 32);
+		ccsr_write4(OCP85XX_LAWBARL(n), bar);
+		ccsr_write4(OCP85XX_LAWSR_QORIQ(n), sr);
+		ccsr_read4(OCP85XX_LAWSR_QORIQ(n));
+	} else {
+		ccsr_write4(OCP85XX_LAWBAR(n), bar >> 12);
+		ccsr_write4(OCP85XX_LAWSR_85XX(n), sr);
+		ccsr_read4(OCP85XX_LAWSR_85XX(n));
+	}
+
+	/*
+	 * The last write to LAWAR should be followed by a read
+	 * of LAWAR before any device try to use any of windows.
+	 * What more the read of LAWAR should be followed by isync
+	 * instruction.
+	 */
+
+	isync();
+}
+
+static inline void
+law_read(uint32_t n, uint64_t *bar, uint32_t *sr)
+{
+
+	if (mpc85xx_is_qoriq()) {
+		*bar = (uint64_t)ccsr_read4(OCP85XX_LAWBARH(n)) << 32 |
+		    ccsr_read4(OCP85XX_LAWBARL(n));
+		*sr = ccsr_read4(OCP85XX_LAWSR_QORIQ(n));
+	} else {
+		*bar = (uint64_t)ccsr_read4(OCP85XX_LAWBAR(n)) << 12;
+		*sr = ccsr_read4(OCP85XX_LAWSR_85XX(n));
+	}
+}
+
+static int
+law_find_free(void)
+{
+	uint32_t i,sr;
+	uint64_t bar;
+	int law_max;
+
+	law_max = law_getmax();
+	/* Find free LAW */
+	for (i = 0; i < law_max; i++) {
+		law_read(i, &bar, &sr);
+		if ((sr & 0x80000000) == 0)
+			break;
+	}
+
+	return (i);
+}
+
+#define	_LAW_SR(trgt,size)	(0x80000000 | (trgt << 20) | \
+				(flsl(size + (size - 1)) - 2))
+
+int
+law_enable(int trgt, uint64_t bar, uint32_t size)
+{
+	uint64_t bar_tmp;
+	uint32_t sr, sr_tmp;
+	int i, law_max;
+
+	if (size == 0)
+		return (0);
+
+	law_max = law_getmax();
+	sr = _LAW_SR(trgt, size);
+
+	/* Bail if already programmed. */
+	for (i = 0; i < law_max; i++) {
+		law_read(i, &bar_tmp, &sr_tmp);
+		if (sr == sr_tmp && bar == bar_tmp)
+			return (0);
+	}
+
+	/* Find an unused access window. */
+	i = law_find_free();
+
+	if (i == law_max)
+		return (ENOSPC);
+
+	law_write(i, bar, sr);
+	return (0);
+}
+
+int
+law_disable(int trgt, uint64_t bar, uint32_t size)
+{
+	uint64_t bar_tmp;
+	uint32_t sr, sr_tmp;
+	int i, law_max;
+
+	law_max = law_getmax();
+	sr = _LAW_SR(trgt, size);
+
+	/* Find and disable requested LAW. */
+	for (i = 0; i < law_max; i++) {
+		law_read(i, &bar_tmp, &sr_tmp);
+		if (sr == sr_tmp && bar == bar_tmp) {
+			law_write(i, 0, 0);
+			return (0);
+		}
+	}
+
+	return (ENOENT);
+}
+
+int
+law_pci_target(struct resource *res, int *trgt_mem, int *trgt_io)
+{
+	u_long start;
+	uint32_t ver;
+	int trgt, rv;
+
+	ver = SVR_VER(mfspr(SPR_SVR));
+
+	start = rman_get_start(res) & 0xf000;
+
+	rv = 0;
+	trgt = -1;
+	switch (start) {
+	case 0x0000:
+	case 0x8000:
+		trgt = 0;
+		break;
+	case 0x1000:
+	case 0x9000:
+		trgt = 1;
+		break;
+	case 0x2000:
+	case 0xa000:
+		if (ver == SVR_MPC8548E || ver == SVR_MPC8548)
+			trgt = 3;
+		else
+			trgt = 2;
+		break;
+	case 0x3000:
+	case 0xb000:
+		if (ver == SVR_MPC8548E || ver == SVR_MPC8548)
+			rv = EINVAL;
+		else
+			trgt = 3;
+		break;
+	default:
+		rv = ENXIO;
+	}
+	if (rv == 0) {
+		*trgt_mem = trgt;
+		*trgt_io = trgt;
+	}
+	return (rv);
+}
+
+static void
+l3cache_inval(void)
+{
+
+	/* Flash invalidate the CPC and clear all the locks */
+	ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_FI |
+	    OCP85XX_CPC_CSR0_LFC);
+	while (ccsr_read4(OCP85XX_CPC_CSR0) & (OCP85XX_CPC_CSR0_FI |
+	    OCP85XX_CPC_CSR0_LFC))
+		;
+}
+
+static void
+l3cache_enable(void)
+{
+
+	ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_CE |
+	    OCP85XX_CPC_CSR0_PE);
+	/* Read back to sync write */
+	ccsr_read4(OCP85XX_CPC_CSR0);
+}
+
+void
+mpc85xx_enable_l3_cache(void)
+{
+	uint32_t csr, size, ver;
+
+	/* Enable L3 CoreNet Platform Cache (CPC) */
+	ver = SVR_VER(mfspr(SPR_SVR));
+	if (ver == SVR_P2041 || ver == SVR_P2041E || ver == SVR_P3041 ||
+	    ver == SVR_P3041E || ver == SVR_P5020 || ver == SVR_P5020E) {
+		csr = ccsr_read4(OCP85XX_CPC_CSR0);
+		if ((csr & OCP85XX_CPC_CSR0_CE) == 0) {
+			l3cache_inval();
+			l3cache_enable();
+		}
+
+		csr = ccsr_read4(OCP85XX_CPC_CSR0);
+		if ((boothowto & RB_VERBOSE) != 0 ||
+		    (csr & OCP85XX_CPC_CSR0_CE) == 0) {
+			size = OCP85XX_CPC_CFG0_SZ_K(ccsr_read4(OCP85XX_CPC_CFG0));
+			printf("L3 Corenet Platform Cache: %d KB %sabled\n",
+			    size, (csr & OCP85XX_CPC_CSR0_CE) == 0 ?
+			    "dis" : "en");
+		}
+	}
+}
+
+int
+mpc85xx_is_qoriq(void)
+{
+	uint16_t pvr = mfpvr() >> 16;
+
+	/* QorIQ register set is only in e500mc and derivative core based SoCs. */
+	if (pvr == FSL_E500mc || pvr == FSL_E5500 || pvr == FSL_E6500)
+		return (1);
+
+	return (0);
+}
+
+uint32_t
+mpc85xx_get_platform_clock(void)
+{
+	phandle_t soc;
+	static uint32_t freq;
+
+	if (freq != 0)
+		return (freq);
+
+	soc = OF_finddevice("/soc");
+
+	/* freq isn't modified on error. */
+	OF_getencprop(soc, "bus-frequency", (void *)&freq, sizeof(freq));
+
+	return (freq);
+}
+
+uint32_t
+mpc85xx_get_system_clock(void)
+{
+	uint32_t freq;
+
+	freq = mpc85xx_get_platform_clock();
+
+	return (freq / 2);
+}
diff --git a/freebsd/sys/powerpc/mpc85xx/mpc85xx.h b/freebsd/sys/powerpc/mpc85xx/mpc85xx.h
new file mode 100644
index 00000000..1a0be6cb
--- /dev/null
+++ b/freebsd/sys/powerpc/mpc85xx/mpc85xx.h
@@ -0,0 +1,177 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (C) 2008 Semihalf, Rafal Jaworowski
+ * Copyright 2006 by Juniper Networks.
+ * All rights reserved.
+ *
+ * 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 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MPC85XX_H_
+#define _MPC85XX_H_
+
+#include <machine/platformvar.h>
+
+/*
+ * Configuration control and status registers
+ */
+extern vm_offset_t		ccsrbar_va;
+extern vm_paddr_t		ccsrbar_pa;
+extern vm_size_t		ccsrbar_size;
+#define CCSRBAR_VA		ccsrbar_va
+#define	OCP85XX_CCSRBAR		(CCSRBAR_VA + 0x0)
+#define	OCP85XX_BPTR		(CCSRBAR_VA + 0x20)
+
+#define	OCP85XX_BSTRH		(CCSRBAR_VA + 0x20)
+#define	OCP85XX_BSTRL		(CCSRBAR_VA + 0x24)
+#define	OCP85XX_BSTAR		(CCSRBAR_VA + 0x28)
+
+#define	OCP85XX_COREDISR	(CCSRBAR_VA + 0xE0094)
+#define	OCP85XX_BRR		(CCSRBAR_VA + 0xE00E4)
+
+/*
+ * Run Control and Power Management registers
+ */
+#define CCSR_CTBENR		(CCSRBAR_VA + 0xE2084)
+#define CCSR_CTBCKSELR		(CCSRBAR_VA + 0xE208C)
+#define CCSR_CTBCHLTCR		(CCSRBAR_VA + 0xE2094)
+
+/*
+ * DDR Memory controller.
+ */
+#define	OCP85XX_DDR1_CS0_CONFIG		(CCSRBAR_VA + 0x8080)
+
+/*
+ * E500 Coherency Module registers
+ */
+#define	OCP85XX_EEBPCR		(CCSRBAR_VA + 0x1010)
+
+/*
+ * Local access registers
+ */
+/* Write order: OCP_LAWBARH -> OCP_LAWBARL -> OCP_LAWSR */
+#define	OCP85XX_LAWBARH(n)	(CCSRBAR_VA + 0xc00 + 0x10 * (n))
+#define	OCP85XX_LAWBARL(n)	(CCSRBAR_VA + 0xc04 + 0x10 * (n))
+#define	OCP85XX_LAWSR_QORIQ(n)	(CCSRBAR_VA + 0xc08 + 0x10 * (n))
+#define	OCP85XX_LAWBAR(n)	(CCSRBAR_VA + 0xc08 + 0x10 * (n))
+#define	OCP85XX_LAWSR_85XX(n)	(CCSRBAR_VA + 0xc10 + 0x10 * (n))
+#define	OCP85XX_LAWSR(n)	(mpc85xx_is_qoriq() ? OCP85XX_LAWSR_QORIQ(n) : \
+				 OCP85XX_LAWSR_85XX(n))
+
+/* Attribute register */
+#define	OCP85XX_ENA_MASK	0x80000000
+#define	OCP85XX_DIS_MASK	0x7fffffff
+
+#define	OCP85XX_TGTIF_LBC_QORIQ	0x1f
+#define	OCP85XX_TGTIF_RAM_INTL_QORIQ	0x14
+#define	OCP85XX_TGTIF_RAM1_QORIQ	0x10
+#define	OCP85XX_TGTIF_RAM2_QORIQ	0x11
+#define	OCP85XX_TGTIF_BMAN		0x18
+#define	OCP85XX_TGTIF_DCSR		0x1D
+#define	OCP85XX_TGTIF_QMAN		0x3C
+#define	OCP85XX_TRGT_SHIFT_QORIQ	20
+
+#define	OCP85XX_TGTIF_LBC_85XX	0x04
+#define	OCP85XX_TGTIF_RAM_INTL_85XX	0x0b
+#define	OCP85XX_TGTIF_RIO_85XX	0x0c
+#define	OCP85XX_TGTIF_RAM1_85XX	0x0f
+#define	OCP85XX_TGTIF_RAM2_85XX	0x16
+
+#define	OCP85XX_TGTIF_LBC	\
+    (mpc85xx_is_qoriq() ? OCP85XX_TGTIF_LBC_QORIQ : OCP85XX_TGTIF_LBC_85XX)
+#define	OCP85XX_TGTIF_RAM_INTL	\
+     (mpc85xx_is_qoriq() ? OCP85XX_TGTIF_RAM_INTL_QORIQ : OCP85XX_TGTIF_RAM_INTL_85XX)
+#define	OCP85XX_TGTIF_RIO	\
+      (mpc85xx_is_qoriq() ? OCP85XX_TGTIF_RIO_QORIQ : OCP85XX_TGTIF_RIO_85XX)
+#define	OCP85XX_TGTIF_RAM1	\
+       (mpc85xx_is_qoriq() ? OCP85XX_TGTIF_RAM1_QORIQ : OCP85XX_TGTIF_RAM1_85XX)
+#define	OCP85XX_TGTIF_RAM2	\
+	(mpc85xx_is_qoriq() ? OCP85XX_TGTIF_RAM2_QORIQ : OCP85XX_TGTIF_RAM2_85XX)
+
+/*
+ * L2 cache registers
+ */
+#define OCP85XX_L2CTL		(CCSRBAR_VA + 0x20000)
+
+/*
+ * L3 CoreNet platform cache (CPC) registers
+ */
+#define	OCP85XX_CPC_CSR0		(CCSRBAR_VA + 0x10000)
+#define	  OCP85XX_CPC_CSR0_CE		  0x80000000
+#define	  OCP85XX_CPC_CSR0_PE		  0x40000000
+#define	  OCP85XX_CPC_CSR0_FI		  0x00200000
+#define	  OCP85XX_CPC_CSR0_WT		  0x00080000
+#define	  OCP85XX_CPC_CSR0_FL		  0x00000800
+#define	  OCP85XX_CPC_CSR0_LFC		  0x00000400
+#define	OCP85XX_CPC_CFG0		(CCSRBAR_VA + 0x10008)
+#define	  OCP85XX_CPC_CFG_SZ_MASK	  0x00003fff
+#define	  OCP85XX_CPC_CFG0_SZ_K(x)	  (((x) & OCP85XX_CPC_CFG_SZ_MASK) << 6)
+
+/*
+ * Power-On Reset configuration
+ */
+#define	OCP85XX_PORDEVSR	(CCSRBAR_VA + 0xe000c)
+#define OCP85XX_PORDEVSR_IO_SEL	0x00780000
+#define OCP85XX_PORDEVSR_IO_SEL_SHIFT 19
+
+#define	OCP85XX_PORDEVSR2	(CCSRBAR_VA + 0xe0014)
+
+/*
+ * Status Registers.
+ */
+#define	OCP85XX_RSTCR		(CCSRBAR_VA + 0xe00b0)
+
+#define	OCP85XX_CLKDVDR		(CCSRBAR_VA + 0xe0800)
+#define	  OCP85XX_CLKDVDR_PXCKEN	  0x80000000
+#define	  OCP85XX_CLKDVDR_SSICKEN	  0x20000000
+#define	  OCP85XX_CLKDVDR_PXCKINV	  0x10000000
+#define	  OCP85XX_CLKDVDR_PXCLK_MASK	  0x00FF0000
+#define	  OCP85XX_CLKDVDR_SSICLK_MASK	  0x000000FF
+
+/*
+ * Run Control/Power Management Registers.
+ */
+#define	OCP85XX_RCPM_CDOZSR	(CCSRBAR_VA + 0xe2004)
+#define	OCP85XX_RCPM_CDOZCR	(CCSRBAR_VA + 0xe200c)
+
+/*
+ * Prototypes.
+ */
+uint32_t ccsr_read4(uintptr_t addr);
+void ccsr_write4(uintptr_t addr, uint32_t val);
+int law_enable(int trgt, uint64_t bar, uint32_t size);
+int law_disable(int trgt, uint64_t bar, uint32_t size);
+int law_getmax(void);
+int law_pci_target(struct resource *, int *, int *);
+
+DECLARE_CLASS(mpc85xx_platform);
+int mpc85xx_attach(platform_t);
+
+void mpc85xx_enable_l3_cache(void);
+int mpc85xx_is_qoriq(void);
+uint32_t mpc85xx_get_platform_clock(void);
+uint32_t mpc85xx_get_system_clock(void);
+
+#endif /* _MPC85XX_H_ */
diff --git a/freebsd/sys/powerpc/mpc85xx/pci_mpc85xx.c b/freebsd/sys/powerpc/mpc85xx/pci_mpc85xx.c
new file mode 100644
index 00000000..f615fafa
--- /dev/null
+++ b/freebsd/sys/powerpc/mpc85xx/pci_mpc85xx.c
@@ -0,0 +1,959 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright 2006-2007 by Juniper Networks.
+ * Copyright 2008 Semihalf.
+ * Copyright 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ * From: FreeBSD: src/sys/powerpc/mpc85xx/pci_ocp.c,v 1.9 2010/03/23 23:46:28 marcel
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ktr.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/rman.h>
+#include <sys/endian.h>
+#include <sys/vmem.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofwpci.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
+
+#include <rtems/bsd/local/ofw_bus_if.h>
+#include <rtems/bsd/local/pcib_if.h>
+#include <rtems/bsd/local/pic_if.h>
+
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+#define	REG_CFG_ADDR	0x0000
+#define	CONFIG_ACCESS_ENABLE	0x80000000
+
+#define	REG_CFG_DATA	0x0004
+#define	REG_INT_ACK	0x0008
+
+#define	REG_PEX_IP_BLK_REV1	0x0bf8
+#define	  IP_MJ_M		  0x0000ff00
+#define	  IP_MJ_S		  8
+#define	  IP_MN_M		  0x000000ff
+#define	  IP_MN_S		  0
+
+#define	REG_POTAR(n)	(0x0c00 + 0x20 * (n))
+#define	REG_POTEAR(n)	(0x0c04 + 0x20 * (n))
+#define	REG_POWBAR(n)	(0x0c08 + 0x20 * (n))
+#define	REG_POWAR(n)	(0x0c10 + 0x20 * (n))
+
+#define	REG_PITAR(n)	(0x0e00 - 0x20 * (n))
+#define	REG_PIWBAR(n)	(0x0e08 - 0x20 * (n))
+#define	REG_PIWBEAR(n)	(0x0e0c - 0x20 * (n))
+#define	REG_PIWAR(n)	(0x0e10 - 0x20 * (n))
+#define	  PIWAR_EN	  0x80000000
+#define	  PIWAR_PF	  0x40000000
+#define	  PIWAR_TRGT_M	  0x00f00000
+#define	  PIWAR_TRGT_S	  20
+#define	  PIWAR_TRGT_CCSR	  0xe
+#define	  PIWAR_TRGT_LOCAL	  0xf
+
+#define	REG_PEX_MES_DR	0x0020
+#define	REG_PEX_MES_IER	0x0028
+#define	REG_PEX_ERR_DR	0x0e00
+#define	REG_PEX_ERR_EN	0x0e08
+
+#define	REG_PEX_ERR_DR		0x0e00
+#define	REG_PEX_ERR_DR_ME	0x80000000
+#define	REG_PEX_ERR_DR_PCT	0x800000
+#define	REG_PEX_ERR_DR_PAT	0x400000
+#define	REG_PEX_ERR_DR_PCAC	0x200000
+#define	REG_PEX_ERR_DR_PNM	0x100000
+#define	REG_PEX_ERR_DR_CDNSC	0x80000
+#define	REG_PEX_ERR_DR_CRSNC	0x40000
+#define	REG_PEX_ERR_DR_ICCA	0x20000
+#define	REG_PEX_ERR_DR_IACA	0x10000
+#define	REG_PEX_ERR_DR_CRST	0x8000
+#define	REG_PEX_ERR_DR_MIS	0x4000
+#define	REG_PEX_ERR_DR_IOIS	0x2000
+#define	REG_PEX_ERR_DR_CIS	0x1000
+#define	REG_PEX_ERR_DR_CIEP	0x800
+#define	REG_PEX_ERR_DR_IOIEP	0x400
+#define	REG_PEX_ERR_DR_OAC	0x200
+#define	REG_PEX_ERR_DR_IOIA	0x100
+#define	REG_PEX_ERR_DR_IMBA	0x80
+#define	REG_PEX_ERR_DR_IIOBA	0x40
+#define	REG_PEX_ERR_DR_LDDE	0x20
+#define	REG_PEX_ERR_EN		0x0e08
+
+#define PCIR_LTSSM	0x404
+#define LTSSM_STAT_L0	0x16
+
+#define	DEVFN(b, s, f)	((b << 16) | (s << 8) | f)
+
+#define	FSL_NUM_MSIS		256	/* 8 registers of 32 bits (8 hardware IRQs) */
+
+struct fsl_pcib_softc {
+	struct ofw_pci_softc pci_sc;
+	device_t	sc_dev;
+	struct mtx	sc_cfg_mtx;
+	int		sc_ip_maj;
+	int		sc_ip_min;
+
+	int		sc_iomem_target;
+	bus_addr_t	sc_iomem_start, sc_iomem_end;
+	int		sc_ioport_target;
+	bus_addr_t	sc_ioport_start, sc_ioport_end;
+
+	struct resource *sc_res;
+	bus_space_handle_t sc_bsh;
+	bus_space_tag_t	sc_bst;
+	int		sc_rid;
+
+	struct resource	*sc_irq_res;
+	void		*sc_ih;
+
+	int		sc_busnr;
+	int		sc_pcie;
+	uint8_t		sc_pcie_capreg;		/* PCI-E Capability Reg Set */
+};
+
+struct fsl_pcib_err_dr {
+	const char	*msg;
+	uint32_t	err_dr_mask;
+};
+
+struct fsl_msi_map {
+	SLIST_ENTRY(fsl_msi_map) slist;
+	uint32_t	irq_base;
+	bus_addr_t	target;
+};
+
+SLIST_HEAD(msi_head, fsl_msi_map) fsl_msis = SLIST_HEAD_INITIALIZER(msi_head);
+
+static const struct fsl_pcib_err_dr pci_err[] = {
+	{"ME",		REG_PEX_ERR_DR_ME},
+	{"PCT",		REG_PEX_ERR_DR_PCT},
+	{"PAT",		REG_PEX_ERR_DR_PAT},
+	{"PCAC",	REG_PEX_ERR_DR_PCAC},
+	{"PNM",		REG_PEX_ERR_DR_PNM},
+	{"CDNSC",	REG_PEX_ERR_DR_CDNSC},
+	{"CRSNC",	REG_PEX_ERR_DR_CRSNC},
+	{"ICCA",	REG_PEX_ERR_DR_ICCA},
+	{"IACA",	REG_PEX_ERR_DR_IACA},
+	{"CRST",	REG_PEX_ERR_DR_CRST},
+	{"MIS",		REG_PEX_ERR_DR_MIS},
+	{"IOIS",	REG_PEX_ERR_DR_IOIS},
+	{"CIS",		REG_PEX_ERR_DR_CIS},
+	{"CIEP",	REG_PEX_ERR_DR_CIEP},
+	{"IOIEP",	REG_PEX_ERR_DR_IOIEP},
+	{"OAC",		REG_PEX_ERR_DR_OAC},
+	{"IOIA",	REG_PEX_ERR_DR_IOIA},
+	{"IMBA",	REG_PEX_ERR_DR_IMBA},
+	{"IIOBA",	REG_PEX_ERR_DR_IIOBA},
+	{"LDDE",	REG_PEX_ERR_DR_LDDE}
+};
+
+/* Local forward declerations. */
+static uint32_t fsl_pcib_cfgread(struct fsl_pcib_softc *, u_int, u_int, u_int,
+    u_int, int);
+static void fsl_pcib_cfgwrite(struct fsl_pcib_softc *, u_int, u_int, u_int,
+    u_int, uint32_t, int);
+static int fsl_pcib_decode_win(phandle_t, struct fsl_pcib_softc *);
+static void fsl_pcib_err_init(device_t);
+static void fsl_pcib_inbound(struct fsl_pcib_softc *, int, int, uint64_t,
+    uint64_t, uint64_t);
+static void fsl_pcib_outbound(struct fsl_pcib_softc *, int, int, uint64_t,
+    uint64_t, uint64_t);
+
+/* Forward declerations. */
+static int fsl_pcib_attach(device_t);
+static int fsl_pcib_detach(device_t);
+static int fsl_pcib_probe(device_t);
+
+static int fsl_pcib_maxslots(device_t);
+static uint32_t fsl_pcib_read_config(device_t, u_int, u_int, u_int, u_int, int);
+static void fsl_pcib_write_config(device_t, u_int, u_int, u_int, u_int,
+    uint32_t, int);
+static int fsl_pcib_alloc_msi(device_t dev, device_t child,
+    int count, int maxcount, int *irqs);
+static int fsl_pcib_release_msi(device_t dev, device_t child,
+    int count, int *irqs);
+static int fsl_pcib_alloc_msix(device_t dev, device_t child, int *irq);
+static int fsl_pcib_release_msix(device_t dev, device_t child, int irq);
+static int fsl_pcib_map_msi(device_t dev, device_t child,
+    int irq, uint64_t *addr, uint32_t *data);
+
+static vmem_t *msi_vmem;	/* Global MSI vmem, holds all MSI ranges. */
+
+/*
+ * Bus interface definitions.
+ */
+static device_method_t fsl_pcib_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		fsl_pcib_probe),
+	DEVMETHOD(device_attach,	fsl_pcib_attach),
+	DEVMETHOD(device_detach,	fsl_pcib_detach),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_maxslots,	fsl_pcib_maxslots),
+	DEVMETHOD(pcib_read_config,	fsl_pcib_read_config),
+	DEVMETHOD(pcib_write_config,	fsl_pcib_write_config),
+	DEVMETHOD(pcib_alloc_msi,	fsl_pcib_alloc_msi),
+	DEVMETHOD(pcib_release_msi,	fsl_pcib_release_msi),
+	DEVMETHOD(pcib_alloc_msix,	fsl_pcib_alloc_msix),
+	DEVMETHOD(pcib_release_msix,	fsl_pcib_release_msix),
+	DEVMETHOD(pcib_map_msi,		fsl_pcib_map_msi),
+
+	DEVMETHOD_END
+};
+
+static devclass_t fsl_pcib_devclass;
+
+DEFINE_CLASS_1(pcib, fsl_pcib_driver, fsl_pcib_methods,
+    sizeof(struct fsl_pcib_softc), ofw_pci_driver);
+EARLY_DRIVER_MODULE(pcib, ofwbus, fsl_pcib_driver, fsl_pcib_devclass, 0, 0,
+    BUS_PASS_BUS);
+
+static void
+fsl_pcib_err_intr(void *v)
+{
+	struct fsl_pcib_softc *sc;
+	device_t dev;
+	uint32_t err_reg, clear_reg;
+	uint8_t i;
+
+	dev = (device_t)v;
+	sc = device_get_softc(dev);
+
+	clear_reg = 0;
+	err_reg = bus_space_read_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_DR);
+
+	/* Check which one error occurred */
+	for (i = 0; i < sizeof(pci_err)/sizeof(struct fsl_pcib_err_dr); i++) {
+		if (err_reg & pci_err[i].err_dr_mask) {
+			device_printf(dev, "PCI %d: report %s error\n",
+			    device_get_unit(dev), pci_err[i].msg);
+			clear_reg |= pci_err[i].err_dr_mask;
+		}
+	}
+
+	/* Clear pending errors */
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_DR, clear_reg);
+}
+
+static int
+fsl_pcib_probe(device_t dev)
+{
+
+	if (ofw_bus_get_type(dev) == NULL ||
+	    strcmp(ofw_bus_get_type(dev), "pci") != 0)
+		return (ENXIO);
+
+	if (!(ofw_bus_is_compatible(dev, "fsl,mpc8540-pci") ||
+	    ofw_bus_is_compatible(dev, "fsl,mpc8540-pcie") ||
+	    ofw_bus_is_compatible(dev, "fsl,mpc8548-pcie") ||
+	    ofw_bus_is_compatible(dev, "fsl,p5020-pcie") ||
+	    ofw_bus_is_compatible(dev, "fsl,qoriq-pcie-v2.2") ||
+	    ofw_bus_is_compatible(dev, "fsl,qoriq-pcie")))
+		return (ENXIO);
+
+	device_set_desc(dev, "Freescale Integrated PCI/PCI-E Controller");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+fsl_pcib_attach(device_t dev)
+{
+	struct fsl_pcib_softc *sc;
+	phandle_t node;
+	uint32_t cfgreg, brctl, ipreg;
+	int error, rid;
+	uint8_t ltssm, capptr;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+
+	sc->sc_rid = 0;
+	sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
+	    RF_ACTIVE);
+	if (sc->sc_res == NULL) {
+		device_printf(dev, "could not map I/O memory\n");
+		return (ENXIO);
+	}
+	sc->sc_bst = rman_get_bustag(sc->sc_res);
+	sc->sc_bsh = rman_get_bushandle(sc->sc_res);
+	sc->sc_busnr = 0;
+
+	ipreg = bus_read_4(sc->sc_res, REG_PEX_IP_BLK_REV1);
+	sc->sc_ip_min = (ipreg & IP_MN_M) >> IP_MN_S;
+	sc->sc_ip_maj = (ipreg & IP_MJ_M) >> IP_MJ_S;
+	mtx_init(&sc->sc_cfg_mtx, "pcicfg", NULL, MTX_SPIN);
+
+	cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_VENDOR, 2);
+	if (cfgreg != 0x1057 && cfgreg != 0x1957)
+		goto err;
+
+	capptr = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_CAP_PTR, 1);
+	while (capptr != 0) {
+		cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, capptr, 2);
+		switch (cfgreg & 0xff) {
+		case PCIY_PCIX:
+			break;
+		case PCIY_EXPRESS:
+			sc->sc_pcie = 1;
+			sc->sc_pcie_capreg = capptr;
+			break;
+		}
+		capptr = (cfgreg >> 8) & 0xff;
+	}
+
+	node = ofw_bus_get_node(dev);
+
+	/*
+	 * Initialize generic OF PCI interface (ranges, etc.)
+	 */
+
+	error = ofw_pci_init(dev);
+	if (error)
+		return (error);
+
+	/*
+	 * Configure decode windows for PCI(E) access.
+	 */
+	if (fsl_pcib_decode_win(node, sc) != 0)
+		goto err;
+
+	cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_COMMAND, 2);
+	cfgreg |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
+	    PCIM_CMD_PORTEN;
+	fsl_pcib_cfgwrite(sc, 0, 0, 0, PCIR_COMMAND, cfgreg, 2);
+
+	/* Reset the bus.  Needed for Radeon video cards. */
+	brctl = fsl_pcib_read_config(sc->sc_dev, 0, 0, 0,
+	    PCIR_BRIDGECTL_1, 1);
+	brctl |= PCIB_BCR_SECBUS_RESET;
+	fsl_pcib_write_config(sc->sc_dev, 0, 0, 0,
+	    PCIR_BRIDGECTL_1, brctl, 1);
+	DELAY(100000);
+	brctl &= ~PCIB_BCR_SECBUS_RESET;
+	fsl_pcib_write_config(sc->sc_dev, 0, 0, 0,
+	    PCIR_BRIDGECTL_1, brctl, 1);
+	DELAY(100000);
+
+	if (sc->sc_pcie) {
+		ltssm = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_LTSSM, 1);
+		if (ltssm < LTSSM_STAT_L0) {
+			if (bootverbose)
+				printf("PCI %d: no PCIE link, skipping\n",
+				    device_get_unit(dev));
+			return (0);
+		}
+	}
+
+	/* Allocate irq */
+	rid = 0;
+	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+	    RF_ACTIVE | RF_SHAREABLE);
+	if (sc->sc_irq_res == NULL) {
+		error = fsl_pcib_detach(dev);
+		if (error != 0) {
+			device_printf(dev,
+			    "Detach of the driver failed with error %d\n",
+			    error);
+		}
+		return (ENXIO);
+	}
+
+	/* Setup interrupt handler */
+	error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+	    NULL, fsl_pcib_err_intr, dev, &sc->sc_ih);
+	if (error != 0) {
+		device_printf(dev, "Could not setup irq, %d\n", error);
+		sc->sc_ih = NULL;
+		error = fsl_pcib_detach(dev);
+		if (error != 0) {
+			device_printf(dev,
+			    "Detach of the driver failed with error %d\n",
+			    error);
+		}
+		return (ENXIO);
+	}
+
+	fsl_pcib_err_init(dev);
+
+	return (ofw_pci_attach(dev));
+
+err:
+	return (ENXIO);
+}
+
+static uint32_t
+fsl_pcib_cfgread(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
+    u_int reg, int bytes)
+{
+	uint32_t addr, data;
+
+	addr = CONFIG_ACCESS_ENABLE;
+	addr |= (bus & 0xff) << 16;
+	addr |= (slot & 0x1f) << 11;
+	addr |= (func & 0x7) << 8;
+	addr |= reg & 0xfc;
+	if (sc->sc_pcie)
+		addr |= (reg & 0xf00) << 16;
+
+	mtx_lock_spin(&sc->sc_cfg_mtx);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr);
+
+	switch (bytes) {
+	case 1:
+		data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
+		    REG_CFG_DATA + (reg & 3));
+		break;
+	case 2:
+		data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh,
+		    REG_CFG_DATA + (reg & 2)));
+		break;
+	case 4:
+		data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+		    REG_CFG_DATA));
+		break;
+	default:
+		data = ~0;
+		break;
+	}
+	mtx_unlock_spin(&sc->sc_cfg_mtx);
+	return (data);
+}
+
+static void
+fsl_pcib_cfgwrite(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
+    u_int reg, uint32_t data, int bytes)
+{
+	uint32_t addr;
+
+	addr = CONFIG_ACCESS_ENABLE;
+	addr |= (bus & 0xff) << 16;
+	addr |= (slot & 0x1f) << 11;
+	addr |= (func & 0x7) << 8;
+	addr |= reg & 0xfc;
+	if (sc->sc_pcie)
+		addr |= (reg & 0xf00) << 16;
+
+	mtx_lock_spin(&sc->sc_cfg_mtx);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr);
+
+	switch (bytes) {
+	case 1:
+		bus_space_write_1(sc->sc_bst, sc->sc_bsh,
+		    REG_CFG_DATA + (reg & 3), data);
+		break;
+	case 2:
+		bus_space_write_2(sc->sc_bst, sc->sc_bsh,
+		    REG_CFG_DATA + (reg & 2), htole16(data));
+		break;
+	case 4:
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+		    REG_CFG_DATA, htole32(data));
+		break;
+	}
+	mtx_unlock_spin(&sc->sc_cfg_mtx);
+}
+
+#if 0
+static void
+dump(struct fsl_pcib_softc *sc)
+{
+	unsigned int i;
+
+#define RD(o)	bus_space_read_4(sc->sc_bst, sc->sc_bsh, o)
+	for (i = 0; i < 5; i++) {
+		printf("POTAR%u  =0x%08x\n", i, RD(REG_POTAR(i)));
+		printf("POTEAR%u =0x%08x\n", i, RD(REG_POTEAR(i)));
+		printf("POWBAR%u =0x%08x\n", i, RD(REG_POWBAR(i)));
+		printf("POWAR%u  =0x%08x\n", i, RD(REG_POWAR(i)));
+	}
+	printf("\n");
+	for (i = 1; i < 4; i++) {
+		printf("PITAR%u  =0x%08x\n", i, RD(REG_PITAR(i)));
+		printf("PIWBAR%u =0x%08x\n", i, RD(REG_PIWBAR(i)));
+		printf("PIWBEAR%u=0x%08x\n", i, RD(REG_PIWBEAR(i)));
+		printf("PIWAR%u  =0x%08x\n", i, RD(REG_PIWAR(i)));
+	}
+	printf("\n");
+#undef RD
+
+	for (i = 0; i < 0x48; i += 4) {
+		printf("cfg%02x=0x%08x\n", i, fsl_pcib_cfgread(sc, 0, 0, 0,
+		    i, 4));
+	}
+}
+#endif
+
+static int
+fsl_pcib_maxslots(device_t dev)
+{
+	struct fsl_pcib_softc *sc = device_get_softc(dev);
+
+	return ((sc->sc_pcie) ? 0 : PCI_SLOTMAX);
+}
+
+static uint32_t
+fsl_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
+    u_int reg, int bytes)
+{
+	struct fsl_pcib_softc *sc = device_get_softc(dev);
+	u_int devfn;
+
+	if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10)
+		return (~0);
+	devfn = DEVFN(bus, slot, func);
+
+	return (fsl_pcib_cfgread(sc, bus, slot, func, reg, bytes));
+}
+
+static void
+fsl_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+    u_int reg, uint32_t val, int bytes)
+{
+	struct fsl_pcib_softc *sc = device_get_softc(dev);
+
+	if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10)
+		return;
+	fsl_pcib_cfgwrite(sc, bus, slot, func, reg, val, bytes);
+}
+
+static void
+fsl_pcib_inbound(struct fsl_pcib_softc *sc, int wnd, int tgt, uint64_t start,
+    uint64_t size, uint64_t pci_start)
+{
+	uint32_t attr, bar, tar;
+
+	KASSERT(wnd > 0, ("%s: inbound window 0 is invalid", __func__));
+
+	attr = PIWAR_EN;
+
+	switch (tgt) {
+	case -1:
+		attr &= ~PIWAR_EN;
+		break;
+	case PIWAR_TRGT_LOCAL:
+		attr |= (ffsl(size) - 2);
+	default:
+		attr |= (tgt << PIWAR_TRGT_S);
+		break;
+	}
+	tar = start >> 12;
+	bar = pci_start >> 12;
+
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PITAR(wnd), tar);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBEAR(wnd), 0);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBAR(wnd), bar);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWAR(wnd), attr);
+}
+
+static void
+fsl_pcib_outbound(struct fsl_pcib_softc *sc, int wnd, int res, uint64_t start,
+    uint64_t size, uint64_t pci_start)
+{
+	uint32_t attr, bar, tar;
+
+	switch (res) {
+	case SYS_RES_MEMORY:
+		attr = 0x80044000 | (ffsll(size) - 2);
+		break;
+	case SYS_RES_IOPORT:
+		attr = 0x80088000 | (ffsll(size) - 2);
+		break;
+	default:
+		attr = 0x0004401f;
+		break;
+	}
+	bar = start >> 12;
+	tar = pci_start >> 12;
+
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTAR(wnd), tar);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTEAR(wnd), 0);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWBAR(wnd), bar);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWAR(wnd), attr);
+}
+
+
+static void
+fsl_pcib_err_init(device_t dev)
+{
+	struct fsl_pcib_softc *sc;
+	uint16_t sec_stat, dsr;
+	uint32_t dcr, err_en;
+
+	sc = device_get_softc(dev);
+
+	sec_stat = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_SECSTAT_1, 2);
+	if (sec_stat)
+		fsl_pcib_cfgwrite(sc, 0, 0, 0, PCIR_SECSTAT_1, 0xffff, 2);
+	if (sc->sc_pcie) {
+		/* Clear error bits */
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_MES_IER,
+		    0xffffffff);
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_MES_DR,
+		    0xffffffff);
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_DR,
+		    0xffffffff);
+
+		dsr = fsl_pcib_cfgread(sc, 0, 0, 0,
+		    sc->sc_pcie_capreg + PCIER_DEVICE_STA, 2);
+		if (dsr)
+			fsl_pcib_cfgwrite(sc, 0, 0, 0,
+			    sc->sc_pcie_capreg + PCIER_DEVICE_STA,
+			    0xffff, 2);
+
+		/* Enable all errors reporting */
+		err_en = 0x00bfff00;
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_EN,
+		    err_en);
+
+		/* Enable error reporting: URR, FER, NFER */
+		dcr = fsl_pcib_cfgread(sc, 0, 0, 0,
+		    sc->sc_pcie_capreg + PCIER_DEVICE_CTL, 4);
+		dcr |= PCIEM_CTL_URR_ENABLE | PCIEM_CTL_FER_ENABLE |
+		    PCIEM_CTL_NFER_ENABLE;
+		fsl_pcib_cfgwrite(sc, 0, 0, 0,
+		    sc->sc_pcie_capreg + PCIER_DEVICE_CTL, dcr, 4);
+	}
+}
+
+static int
+fsl_pcib_detach(device_t dev)
+{
+	struct fsl_pcib_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	mtx_destroy(&sc->sc_cfg_mtx);
+
+	return (bus_generic_detach(dev));
+}
+
+static int
+fsl_pcib_decode_win(phandle_t node, struct fsl_pcib_softc *sc)
+{
+	device_t dev;
+	int error, i, trgt;
+
+	dev = sc->sc_dev;
+
+	fsl_pcib_outbound(sc, 0, -1, 0, 0, 0);
+
+	/*
+	 * Configure LAW decode windows.
+	 */
+	error = law_pci_target(sc->sc_res, &sc->sc_iomem_target,
+	    &sc->sc_ioport_target);
+	if (error != 0) {
+		device_printf(dev, "could not retrieve PCI LAW target info\n");
+		return (error);
+	}
+
+	for (i = 0; i < sc->pci_sc.sc_nrange; i++) {
+		switch (sc->pci_sc.sc_range[i].pci_hi &
+		    OFW_PCI_PHYS_HI_SPACEMASK) {
+		case OFW_PCI_PHYS_HI_SPACE_CONFIG:
+			continue;
+		case OFW_PCI_PHYS_HI_SPACE_IO:
+			trgt = sc->sc_ioport_target;
+			fsl_pcib_outbound(sc, 2, SYS_RES_IOPORT,
+			    sc->pci_sc.sc_range[i].host,
+			    sc->pci_sc.sc_range[i].size,
+			    sc->pci_sc.sc_range[i].pci);
+			sc->sc_ioport_start = sc->pci_sc.sc_range[i].pci;
+			sc->sc_ioport_end = sc->pci_sc.sc_range[i].pci +
+			    sc->pci_sc.sc_range[i].size - 1;
+			break;
+		case OFW_PCI_PHYS_HI_SPACE_MEM32:
+		case OFW_PCI_PHYS_HI_SPACE_MEM64:
+			trgt = sc->sc_iomem_target;
+			fsl_pcib_outbound(sc, 1, SYS_RES_MEMORY,
+			    sc->pci_sc.sc_range[i].host,
+			    sc->pci_sc.sc_range[i].size,
+			    sc->pci_sc.sc_range[i].pci);
+			sc->sc_iomem_start = sc->pci_sc.sc_range[i].pci;
+			sc->sc_iomem_end = sc->pci_sc.sc_range[i].pci +
+			    sc->pci_sc.sc_range[i].size - 1;
+			break;
+		default:
+			panic("Unknown range type %#x\n",
+			    sc->pci_sc.sc_range[i].pci_hi &
+			    OFW_PCI_PHYS_HI_SPACEMASK);
+		}
+		error = law_enable(trgt, sc->pci_sc.sc_range[i].host,
+		    sc->pci_sc.sc_range[i].size);
+		if (error != 0) {
+			device_printf(dev, "could not program LAW for range "
+			    "%d\n", i);
+			return (error);
+		}
+	}
+
+	/*
+	 * Set outbout and inbound windows.
+	 */
+	fsl_pcib_outbound(sc, 3, -1, 0, 0, 0);
+	fsl_pcib_outbound(sc, 4, -1, 0, 0, 0);
+
+	fsl_pcib_inbound(sc, 1, -1, 0, 0, 0);
+	fsl_pcib_inbound(sc, 2, -1, 0, 0, 0);
+	fsl_pcib_inbound(sc, 3, PIWAR_TRGT_LOCAL, 0,
+	    ptoa(Maxmem), 0);
+
+	/* Direct-map the CCSR for MSIs. */
+	/* Freescale PCIe 2.x has a dedicated MSI window. */
+	/* inbound window 8 makes it hit 0xD00 offset, the MSI window. */
+	if (sc->sc_ip_maj >= 2)
+		fsl_pcib_inbound(sc, 8, PIWAR_TRGT_CCSR, ccsrbar_pa,
+		    ccsrbar_size, ccsrbar_pa);
+	else
+		fsl_pcib_inbound(sc, 1, PIWAR_TRGT_CCSR, ccsrbar_pa,
+		    ccsrbar_size, ccsrbar_pa);
+
+	return (0);
+}
+
+static int fsl_pcib_alloc_msi(device_t dev, device_t child,
+    int count, int maxcount, int *irqs)
+{
+	struct fsl_pcib_softc *sc;
+	vmem_addr_t start;
+	int err, i;
+
+	sc = device_get_softc(dev);
+	if (msi_vmem == NULL)
+		return (ENODEV);
+
+	err = vmem_xalloc(msi_vmem, count, powerof2(count), 0, 0,
+	    VMEM_ADDR_MIN, VMEM_ADDR_MAX, M_BESTFIT | M_WAITOK, &start);
+
+	if (err)
+		return (err);
+
+	for (i = 0; i < count; i++)
+		irqs[i] = start + i;
+
+	return (0);
+}
+
+static int fsl_pcib_release_msi(device_t dev, device_t child,
+    int count, int *irqs)
+{
+	if (msi_vmem == NULL)
+		return (ENODEV);
+
+	vmem_xfree(msi_vmem, irqs[0], count);
+	return (0);
+}
+
+static int fsl_pcib_alloc_msix(device_t dev, device_t child, int *irq)
+{
+	return (fsl_pcib_alloc_msi(dev, child, 1, 1, irq));
+}
+
+static int fsl_pcib_release_msix(device_t dev, device_t child, int irq)
+{
+	return (fsl_pcib_release_msi(dev, child, 1, &irq));
+}
+
+static int fsl_pcib_map_msi(device_t dev, device_t child,
+    int irq, uint64_t *addr, uint32_t *data)
+{
+	struct fsl_msi_map *mp;
+
+	SLIST_FOREACH(mp, &fsl_msis, slist) {
+		if (irq >= mp->irq_base && irq < mp->irq_base + FSL_NUM_MSIS)
+			break;
+	}
+
+	if (mp == NULL)
+		return (ENODEV);
+
+	*data = (irq & 255);
+	*addr = ccsrbar_pa + mp->target;
+
+	return (0);
+}
+
+
+/*
+ * Linux device trees put the msi@<x> as children of the SoC, with ranges based
+ * on the CCSR.  Since rman doesn't permit overlapping or sub-ranges between
+ * devices (bus_space_subregion(9) could do it, but let's not touch the PIC
+ * driver just to allocate a subregion for a sibling driver).  This driver will
+ * use ccsr_write() and ccsr_read() instead.
+ */
+
+#define	FSL_NUM_IRQS		8
+#define	FSL_NUM_MSI_PER_IRQ	32
+#define	FSL_MSI_TARGET	0x140
+
+struct fsl_msi_softc {
+	vm_offset_t	sc_base;
+	vm_offset_t	sc_target;
+	int		sc_msi_base_irq;
+	struct fsl_msi_map sc_map;
+	struct fsl_msi_irq {
+		/* This struct gets passed as the filter private data. */
+		struct fsl_msi_softc *sc_ptr;	/* Pointer back to softc. */
+		struct resource *res;
+		int irq;
+		void *cookie;
+		int vectors[FSL_NUM_MSI_PER_IRQ];
+		vm_offset_t reg;
+	} sc_msi_irq[FSL_NUM_IRQS];
+};
+
+static int
+fsl_msi_intr_filter(void *priv)
+{
+	struct fsl_msi_irq *data = priv;
+	uint32_t reg;
+	int i;
+
+	reg = ccsr_read4(ccsrbar_va + data->reg);
+	i = 0;
+	while (reg != 0) {
+		if (reg & 1)
+			powerpc_dispatch_intr(data->vectors[i], NULL);
+		reg >>= 1;
+		i++;
+	}
+
+	return (FILTER_HANDLED);
+}
+
+static int
+fsl_msi_probe(device_t dev)
+{
+	if (!ofw_bus_is_compatible(dev, "fsl,mpic-msi"))
+		return (ENXIO);
+
+	device_set_desc(dev, "Freescale MSI");
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+fsl_msi_attach(device_t dev)
+{
+	struct fsl_msi_softc *sc;
+	struct fsl_msi_irq *irq;
+	int i;
+
+	sc = device_get_softc(dev);
+
+	if (msi_vmem == NULL)
+		msi_vmem = vmem_create("MPIC MSI", 0, 0, 1, 0, M_BESTFIT | M_WAITOK);
+
+	/* Manually play with resource entries. */
+	sc->sc_base = bus_get_resource_start(dev, SYS_RES_MEMORY, 0);
+	sc->sc_map.target = bus_get_resource_start(dev, SYS_RES_MEMORY, 1);
+
+	if (sc->sc_map.target == 0)
+		sc->sc_map.target = sc->sc_base + FSL_MSI_TARGET;
+
+	for (i = 0; i < FSL_NUM_IRQS; i++) {
+		irq = &sc->sc_msi_irq[i];
+		irq->irq = i;
+		irq->reg = sc->sc_base + 16 * i;
+		irq->res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+		    &irq->irq, RF_ACTIVE);
+		bus_setup_intr(dev, irq->res, INTR_TYPE_MISC | INTR_MPSAFE,
+		    fsl_msi_intr_filter, NULL, irq, &irq->cookie);
+	}
+	sc->sc_map.irq_base = powerpc_register_pic(dev, ofw_bus_get_node(dev),
+	    FSL_NUM_MSIS, 0, 0);
+
+	/* Let vmem and the IRQ subsystem work their magic for allocations. */
+	vmem_add(msi_vmem, sc->sc_map.irq_base, FSL_NUM_MSIS, M_WAITOK);
+
+	SLIST_INSERT_HEAD(&fsl_msis, &sc->sc_map, slist);
+
+	return (0);
+}
+
+static void
+fsl_msi_enable(device_t dev, u_int irq, u_int vector, void **priv)
+{
+	struct fsl_msi_softc *sc;
+	struct fsl_msi_irq *irqd;
+
+	sc = device_get_softc(dev);
+
+	irqd = &sc->sc_msi_irq[irq / FSL_NUM_MSI_PER_IRQ];
+	irqd->vectors[irq % FSL_NUM_MSI_PER_IRQ] = vector;
+}
+
+static device_method_t fsl_msi_methods[] = {
+	DEVMETHOD(device_probe,		fsl_msi_probe),
+	DEVMETHOD(device_attach,	fsl_msi_attach),
+
+	DEVMETHOD(pic_enable,		fsl_msi_enable),
+	DEVMETHOD_END
+};
+
+static devclass_t fsl_msi_devclass;
+
+static driver_t fsl_msi_driver = {
+	"fsl_msi",
+	fsl_msi_methods,
+	sizeof(struct fsl_msi_softc)
+};
+
+EARLY_DRIVER_MODULE(fsl_msi, simplebus, fsl_msi_driver, fsl_msi_devclass, 0, 0,
+    BUS_PASS_INTERRUPT + 1);
diff --git a/freebsd/sys/powerpc/mpc85xx/pci_mpc85xx_pcib.c b/freebsd/sys/powerpc/mpc85xx/pci_mpc85xx_pcib.c
new file mode 100644
index 00000000..74a580f5
--- /dev/null
+++ b/freebsd/sys/powerpc/mpc85xx/pci_mpc85xx_pcib.c
@@ -0,0 +1,111 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * Copyright 2015 Justin Hibbits
+ * All rights reserved.
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ * From: FreeBSD: src/sys/powerpc/mpc85xx/pci_ocp.c,v 1.9 2010/03/23 23:46:28 marcel
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ktr.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/endian.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
+
+#include <machine/intr_machdep.h>
+
+#include <rtems/bsd/local/pcib_if.h>
+
+DECLARE_CLASS(ofw_pcib_pci_driver);
+
+struct fsl_pcib_softc {
+        /*
+         * This is here so that we can use pci bridge methods, too - the
+         * generic routines only need the dev, secbus and subbus members
+         * filled.
+         *
+         * XXX: This should be extracted from ofw_pcib_pci.c, and shared in a
+         * header.
+         */
+        struct pcib_softc       ops_pcib_sc;
+	phandle_t		ops_node;
+        struct ofw_bus_iinfo    ops_iinfo;
+};
+
+static int
+fsl_pcib_rc_probe(device_t dev)
+{
+
+	if (pci_get_vendor(dev) != 0x1957)
+		return (ENXIO);
+	if (pci_get_progif(dev) != 0)
+		return (ENXIO);
+	if (pci_get_class(dev) != PCIC_PROCESSOR)
+		return (ENXIO);
+	if (pci_get_subclass(dev) != PCIS_PROCESSOR_POWERPC)
+		return (ENXIO);
+
+	device_set_desc(dev, "MPC85xx Root Complex bridge");
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+static device_method_t fsl_pcib_rc_methods[] = {
+	DEVMETHOD(device_probe,		fsl_pcib_rc_probe),
+	DEVMETHOD_END
+};
+
+static devclass_t fsl_pcib_rc_devclass;
+DEFINE_CLASS_1(pcib, fsl_pcib_rc_driver, fsl_pcib_rc_methods,
+    sizeof(struct fsl_pcib_softc), ofw_pcib_pci_driver);
+EARLY_DRIVER_MODULE(rcpcib, pci, fsl_pcib_rc_driver, fsl_pcib_rc_devclass, 0, 0,
+    BUS_PASS_BUS);
diff --git a/freebsd/sys/powerpc/mpc85xx/platform_mpc85xx.c b/freebsd/sys/powerpc/mpc85xx/platform_mpc85xx.c
new file mode 100644
index 00000000..1d806970
--- /dev/null
+++ b/freebsd/sys/powerpc/mpc85xx/platform_mpc85xx.c
@@ -0,0 +1,710 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2008-2012 Semihalf.
+ * All rights reserved.
+ *
+ * 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 ``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 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 <rtems/bsd/local/opt_platform.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/hid.h>
+#include <machine/_inttypes.h>
+#include <machine/machdep.h>
+#include <machine/md_var.h>
+#include <machine/platform.h>
+#include <machine/platformvar.h>
+#include <machine/smp.h>
+#include <machine/spr.h>
+#include <machine/vmparam.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+#include <rtems/bsd/local/platform_if.h>
+
+#ifdef SMP
+extern void *ap_pcpu;
+extern vm_paddr_t kernload;		/* Kernel physical load address */
+extern uint8_t __boot_page[];		/* Boot page body */
+extern uint32_t bp_kernload;
+extern vm_offset_t __startkernel;
+
+struct cpu_release {
+	uint32_t entry_h;
+	uint32_t entry_l;
+	uint32_t r3_h;
+	uint32_t r3_l;
+	uint32_t reserved;
+	uint32_t pir;
+};
+#endif
+
+extern uint32_t *bootinfo;
+vm_paddr_t ccsrbar_pa;
+vm_offset_t ccsrbar_va;
+vm_size_t ccsrbar_size;
+
+static int cpu, maxcpu;
+
+static device_t rcpm_dev;
+static void dummy_freeze(device_t, bool);
+
+static void (*freeze_timebase)(device_t, bool) = dummy_freeze;
+
+static int mpc85xx_probe(platform_t);
+static void mpc85xx_mem_regions(platform_t, struct mem_region *phys,
+    int *physsz, struct mem_region *avail, int *availsz);
+static u_long mpc85xx_timebase_freq(platform_t, struct cpuref *cpuref);
+static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref);
+static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref);
+static int mpc85xx_smp_get_bsp(platform_t, struct cpuref *cpuref);
+static int mpc85xx_smp_start_cpu(platform_t, struct pcpu *cpu);
+static void mpc85xx_smp_timebase_sync(platform_t, u_long tb, int ap);
+
+static void mpc85xx_reset(platform_t);
+
+static platform_method_t mpc85xx_methods[] = {
+	PLATFORMMETHOD(platform_probe,		mpc85xx_probe),
+	PLATFORMMETHOD(platform_attach,		mpc85xx_attach),
+	PLATFORMMETHOD(platform_mem_regions,	mpc85xx_mem_regions),
+	PLATFORMMETHOD(platform_timebase_freq,	mpc85xx_timebase_freq),
+
+	PLATFORMMETHOD(platform_smp_first_cpu,	mpc85xx_smp_first_cpu),
+	PLATFORMMETHOD(platform_smp_next_cpu,	mpc85xx_smp_next_cpu),
+	PLATFORMMETHOD(platform_smp_get_bsp,	mpc85xx_smp_get_bsp),
+	PLATFORMMETHOD(platform_smp_start_cpu,	mpc85xx_smp_start_cpu),
+	PLATFORMMETHOD(platform_smp_timebase_sync, mpc85xx_smp_timebase_sync),
+
+	PLATFORMMETHOD(platform_reset,		mpc85xx_reset),
+
+	PLATFORMMETHOD_END
+};
+
+DEFINE_CLASS_0(mpc85xx, mpc85xx_platform, mpc85xx_methods, 0);
+
+PLATFORM_DEF(mpc85xx_platform);
+
+static int
+mpc85xx_probe(platform_t plat)
+{
+	u_int pvr = (mfpvr() >> 16) & 0xFFFF;
+
+	switch (pvr) {
+		case FSL_E500v1:
+		case FSL_E500v2:
+		case FSL_E500mc:
+		case FSL_E5500:
+		case FSL_E6500:
+			return (BUS_PROBE_DEFAULT);
+	}
+	return (ENXIO);
+}
+
+int
+mpc85xx_attach(platform_t plat)
+{
+	phandle_t cpus, child, ccsr;
+	const char *soc_name_guesses[] = {"/soc", "soc", NULL};
+	const char **name;
+	pcell_t ranges[6], acells, pacells, scells;
+	uint64_t ccsrbar, ccsrsize;
+	int i;
+
+	if ((cpus = OF_finddevice("/cpus")) != -1) {
+		for (maxcpu = 0, child = OF_child(cpus); child != 0;
+		    child = OF_peer(child), maxcpu++)
+			;
+	} else
+		maxcpu = 1;
+
+	/*
+	 * Locate CCSR region. Irritatingly, there is no way to find it
+	 * unless you already know where it is. Try to infer its location
+	 * from the device tree.
+	 */
+
+	ccsr = -1;
+	for (name = soc_name_guesses; *name != NULL && ccsr == -1; name++)
+		ccsr = OF_finddevice(*name);
+	if (ccsr == -1) {
+		char type[64];
+
+	 	/* That didn't work. Search for devices of type "soc" */
+		child = OF_child(OF_peer(0));
+		for (OF_child(child); child != 0; child = OF_peer(child)) {
+			if (OF_getprop(child, "device_type", type, sizeof(type))
+			    <= 0)
+				continue;
+
+			if (strcmp(type, "soc") == 0) {
+				ccsr = child;
+				break;
+			}
+		}
+	}
+
+	if (ccsr == -1)
+		panic("Could not locate CCSR window!");
+
+	OF_getprop(ccsr, "#size-cells", &scells, sizeof(scells));
+	OF_getprop(ccsr, "#address-cells", &acells, sizeof(acells));
+	OF_searchprop(OF_parent(ccsr), "#address-cells", &pacells,
+	    sizeof(pacells));
+	OF_getprop(ccsr, "ranges", ranges, sizeof(ranges));
+	ccsrbar = ccsrsize = 0;
+	for (i = acells; i < acells + pacells; i++) {
+		ccsrbar <<= 32;
+		ccsrbar |= ranges[i];
+	}
+	for (i = acells + pacells; i < acells + pacells + scells; i++) {
+		ccsrsize <<= 32;
+		ccsrsize |= ranges[i];
+	}
+	ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize);
+	ccsrbar_pa = ccsrbar;
+	ccsrbar_size = ccsrsize;
+
+	mpc85xx_enable_l3_cache();
+
+	return (0);
+}
+
+void
+mpc85xx_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
+    struct mem_region *avail, int *availsz)
+{
+
+	ofw_mem_regions(phys, physsz, avail, availsz);
+}
+
+static u_long
+mpc85xx_timebase_freq(platform_t plat, struct cpuref *cpuref)
+{
+	u_long ticks;
+	phandle_t cpus, child;
+	pcell_t freq;
+
+	if (bootinfo != NULL) {
+		if (bootinfo[0] == 1) {
+			/* Backward compatibility. See 8-STABLE. */
+			ticks = bootinfo[3] >> 3;
+		} else {
+			/* Compatibility with Juniper's loader. */
+			ticks = bootinfo[5] >> 3;
+		}
+	} else
+		ticks = 0;
+
+	if ((cpus = OF_finddevice("/cpus")) == -1)
+		goto out;
+
+	if ((child = OF_child(cpus)) == 0)
+		goto out;
+
+	switch (OF_getproplen(child, "timebase-frequency")) {
+	case 4:
+	{
+		uint32_t tbase;
+		OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase));
+		ticks = tbase;
+		return (ticks);
+	}
+	case 8:
+	{
+		uint64_t tbase;
+		OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase));
+		ticks = tbase;
+		return (ticks);
+	}
+	default:
+		break;
+	}
+
+	freq = 0;
+	if (OF_getprop(child, "bus-frequency", (void *)&freq,
+	    sizeof(freq)) <= 0)
+		goto out;
+
+	if (freq == 0)
+		goto out;
+
+	/*
+	 * Time Base and Decrementer are updated every 8 CCB bus clocks.
+	 * HID0[SEL_TBCLK] = 0
+	 */
+	if (mpc85xx_is_qoriq())
+		ticks = freq / 32;
+	else
+		ticks = freq / 8;
+
+out:
+	if (ticks <= 0)
+		panic("Unable to determine timebase frequency!");
+
+	return (ticks);
+}
+
+static int
+mpc85xx_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
+{
+
+	cpu = 0;
+	cpuref->cr_cpuid = cpu;
+	cpuref->cr_hwref = cpuref->cr_cpuid;
+	if (bootverbose)
+		printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid);
+	cpu++;
+
+	return (0);
+}
+
+static int
+mpc85xx_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
+{
+
+	if (cpu >= maxcpu)
+		return (ENOENT);
+
+	cpuref->cr_cpuid = cpu++;
+	cpuref->cr_hwref = cpuref->cr_cpuid;
+	if (bootverbose)
+		printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid);
+
+	return (0);
+}
+
+static int
+mpc85xx_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
+{
+
+	cpuref->cr_cpuid = mfspr(SPR_PIR);
+	cpuref->cr_hwref = cpuref->cr_cpuid;
+
+	return (0);
+}
+
+#ifdef SMP
+static int
+mpc85xx_smp_start_cpu_epapr(platform_t plat, struct pcpu *pc)
+{
+	vm_paddr_t rel_pa, bptr;
+	volatile struct cpu_release *rel;
+	vm_offset_t rel_va, rel_page;
+	phandle_t node;
+	int i;
+
+	/* If we're calling this, the node already exists. */
+	node = OF_finddevice("/cpus");
+	for (i = 0, node = OF_child(node); i < pc->pc_cpuid;
+	    i++, node = OF_peer(node))
+		;
+	if (OF_getencprop(node, "cpu-release-addr", (pcell_t *)&rel_pa,
+	    sizeof(rel_pa)) == -1) {
+		return (ENOENT);
+	}
+
+	rel_page = kva_alloc(PAGE_SIZE);
+	if (rel_page == 0)
+		return (ENOMEM);
+
+	critical_enter();
+	rel_va = rel_page + (rel_pa & PAGE_MASK);
+	pmap_kenter(rel_page, rel_pa & ~PAGE_MASK);
+	rel = (struct cpu_release *)rel_va;
+	bptr = pmap_kextract((uintptr_t)__boot_page);
+	cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel));
+	rel->pir = pc->pc_cpuid; __asm __volatile("sync");
+	rel->entry_h = (bptr >> 32);
+	rel->entry_l = bptr; __asm __volatile("sync");
+	cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel));
+	if (bootverbose)
+		printf("Waking up CPU %d via CPU release page %p\n",
+		    pc->pc_cpuid, rel);
+	critical_exit();
+	pmap_kremove(rel_page);
+	kva_free(rel_page, PAGE_SIZE);
+
+	return (0);
+}
+#endif
+
+static int
+mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc)
+{
+#ifdef SMP
+	vm_paddr_t bptr;
+	uint32_t reg;
+	int timeout;
+	uintptr_t brr;
+	int cpuid;
+	int epapr_boot = 0;
+	uint32_t tgt;
+
+	if (mpc85xx_is_qoriq()) {
+		reg = ccsr_read4(OCP85XX_COREDISR);
+		cpuid = pc->pc_cpuid;
+
+		if ((reg & (1 << cpuid)) != 0) {
+		    printf("%s: CPU %d is disabled!\n", __func__, pc->pc_cpuid);
+		    return (-1);
+		}
+
+		brr = OCP85XX_BRR;
+	} else {
+		brr = OCP85XX_EEBPCR;
+		cpuid = pc->pc_cpuid + 24;
+	}
+	bp_kernload = kernload;
+	/*
+	 * bp_kernload is in the boot page.  Sync the cache because ePAPR
+	 * booting has the other core(s) already running.
+	 */
+	cpu_flush_dcache(&bp_kernload, sizeof(bp_kernload));
+
+	ap_pcpu = pc;
+	__asm __volatile("msync; isync");
+
+	/* First try the ePAPR way. */
+	if (mpc85xx_smp_start_cpu_epapr(plat, pc) == 0) {
+		epapr_boot = 1;
+		goto spin_wait;
+	}
+
+	reg = ccsr_read4(brr);
+	if ((reg & (1 << cpuid)) != 0) {
+		printf("SMP: CPU %d already out of hold-off state!\n",
+		    pc->pc_cpuid);
+		return (ENXIO);
+	}
+
+	/* Flush caches to have our changes hit DRAM. */
+	cpu_flush_dcache(__boot_page, 4096);
+
+	bptr = pmap_kextract((uintptr_t)__boot_page);
+	KASSERT((bptr & 0xfff) == 0,
+	    ("%s: boot page is not aligned (%#jx)", __func__, (uintmax_t)bptr));
+	if (mpc85xx_is_qoriq()) {
+		/*
+		 * Read DDR controller configuration to select proper BPTR target ID.
+		 *
+		 * On P5020 bit 29 of DDR1_CS0_CONFIG enables DDR controllers
+		 * interleaving. If this bit is set, we have to use
+		 * OCP85XX_TGTIF_RAM_INTL as BPTR target ID. On other QorIQ DPAA SoCs,
+		 * this bit is reserved and always 0.
+		 */
+
+		reg = ccsr_read4(OCP85XX_DDR1_CS0_CONFIG);
+		if (reg & (1 << 29))
+			tgt = OCP85XX_TGTIF_RAM_INTL;
+		else
+			tgt = OCP85XX_TGTIF_RAM1;
+
+		/*
+		 * Set BSTR to the physical address of the boot page
+		 */
+		ccsr_write4(OCP85XX_BSTRH, bptr >> 32);
+		ccsr_write4(OCP85XX_BSTRL, bptr);
+		ccsr_write4(OCP85XX_BSTAR, OCP85XX_ENA_MASK |
+		    (tgt << OCP85XX_TRGT_SHIFT_QORIQ) | (ffsl(PAGE_SIZE) - 2));
+
+		/* Read back OCP85XX_BSTAR to synchronize write */
+		ccsr_read4(OCP85XX_BSTAR);
+
+		/*
+		 * Enable and configure time base on new CPU.
+		 */
+
+		/* Set TB clock source to platform clock / 32 */
+		reg = ccsr_read4(CCSR_CTBCKSELR);
+		ccsr_write4(CCSR_CTBCKSELR, reg & ~(1 << pc->pc_cpuid));
+
+		/* Enable TB */
+		reg = ccsr_read4(CCSR_CTBENR);
+		ccsr_write4(CCSR_CTBENR, reg | (1 << pc->pc_cpuid));
+	} else {
+		/*
+		 * Set BPTR to the physical address of the boot page
+		 */
+		bptr = (bptr >> 12) | 0x80000000u;
+		ccsr_write4(OCP85XX_BPTR, bptr);
+		__asm __volatile("isync; msync");
+	}
+
+	/*
+	 * Release AP from hold-off state
+	 */
+	reg = ccsr_read4(brr);
+	ccsr_write4(brr, reg | (1 << cpuid));
+	__asm __volatile("isync; msync");
+
+spin_wait:
+	timeout = 500;
+	while (!pc->pc_awake && timeout--)
+		DELAY(1000);	/* wait 1ms */
+
+	/*
+	 * Disable boot page translation so that the 4K page at the default
+	 * address (= 0xfffff000) isn't permanently remapped and thus not
+	 * usable otherwise.
+	 */
+	if (!epapr_boot) {
+		if (mpc85xx_is_qoriq())
+			ccsr_write4(OCP85XX_BSTAR, 0);
+		else
+			ccsr_write4(OCP85XX_BPTR, 0);
+		__asm __volatile("isync; msync");
+	}
+
+	if (!pc->pc_awake)
+		panic("SMP: CPU %d didn't wake up.\n", pc->pc_cpuid);
+	return ((pc->pc_awake) ? 0 : EBUSY);
+#else
+	/* No SMP support */
+	return (ENXIO);
+#endif
+}
+
+static void
+mpc85xx_reset(platform_t plat)
+{
+
+	/*
+	 * Try the dedicated reset register first.
+	 * If the SoC doesn't have one, we'll fall
+	 * back to using the debug control register.
+	 */
+	ccsr_write4(OCP85XX_RSTCR, 2);
+
+	/* Clear DBCR0, disables debug interrupts and events. */
+	mtspr(SPR_DBCR0, 0);
+	__asm __volatile("isync");
+
+	/* Enable Debug Interrupts in MSR. */
+	mtmsr(mfmsr() | PSL_DE);
+
+	/* Enable debug interrupts and issue reset. */
+	mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM | DBCR0_RST_SYSTEM);
+
+	printf("Reset failed...\n");
+	while (1)
+		;
+}
+
+static void
+mpc85xx_smp_timebase_sync(platform_t plat, u_long tb, int ap)
+{
+	static volatile bool tb_ready;
+	static volatile int cpu_done;
+
+	if (ap) {
+		/* APs.  Hold off until we get a stable timebase. */
+		while (!tb_ready)
+			atomic_thread_fence_seq_cst();
+		mttb(tb);
+		atomic_add_int(&cpu_done, 1);
+		while (cpu_done < mp_ncpus)
+			atomic_thread_fence_seq_cst();
+	} else {
+		/* BSP */
+		freeze_timebase(rcpm_dev, true);
+		tb_ready = true;
+		mttb(tb);
+		atomic_add_int(&cpu_done, 1);
+		while (cpu_done < mp_ncpus)
+			atomic_thread_fence_seq_cst();
+		freeze_timebase(rcpm_dev, false);
+	}
+}
+
+/* Fallback freeze.  In case no real handler is found in the device tree. */
+static void
+dummy_freeze(device_t dev, bool freeze)
+{
+	/* Nothing to do here, move along. */
+}
+
+
+/* QorIQ Run control/power management timebase management. */
+
+#define	RCPM_CTBENR	0x00000084
+struct mpc85xx_rcpm_softc {
+	struct resource *sc_mem;
+};
+
+static void
+mpc85xx_rcpm_freeze_timebase(device_t dev, bool freeze)
+{
+	struct mpc85xx_rcpm_softc *sc;
+
+	sc = device_get_softc(dev);
+	
+	if (freeze)
+		bus_write_4(sc->sc_mem, RCPM_CTBENR, 0);
+	else
+		bus_write_4(sc->sc_mem, RCPM_CTBENR, (1 << maxcpu) - 1);
+}
+
+static int
+mpc85xx_rcpm_probe(device_t dev)
+{
+	if (!ofw_bus_is_compatible(dev, "fsl,qoriq-rcpm-1.0"))
+		return (ENXIO);
+
+	device_set_desc(dev, "QorIQ Run control and power management");
+	return (BUS_PROBE_GENERIC);
+}
+
+static int
+mpc85xx_rcpm_attach(device_t dev)
+{
+	struct mpc85xx_rcpm_softc *sc;
+	int rid;
+
+	sc = device_get_softc(dev);
+	freeze_timebase = mpc85xx_rcpm_freeze_timebase;
+	rcpm_dev = dev;
+
+	rid = 0;
+	sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+	    RF_ACTIVE | RF_SHAREABLE);
+
+	return (0);
+}
+
+static device_method_t mpc85xx_rcpm_methods[] = {
+	DEVMETHOD(device_probe,		mpc85xx_rcpm_probe),
+	DEVMETHOD(device_attach,	mpc85xx_rcpm_attach),
+	DEVMETHOD_END
+};
+
+static devclass_t mpc85xx_rcpm_devclass;
+
+static driver_t mpc85xx_rcpm_driver = {
+	"rcpm",
+	mpc85xx_rcpm_methods,
+	sizeof(struct mpc85xx_rcpm_softc)
+};
+
+EARLY_DRIVER_MODULE(mpc85xx_rcpm, simplebus, mpc85xx_rcpm_driver,
+	mpc85xx_rcpm_devclass, 0, 0, BUS_PASS_BUS);
+
+
+/* "Global utilities" power management/Timebase management. */
+
+#define	GUTS_DEVDISR	0x00000070
+#define	  DEVDISR_TB0	0x00004000
+#define	  DEVDISR_TB1	0x00001000
+
+struct mpc85xx_guts_softc {
+	struct resource *sc_mem;
+};
+
+static void
+mpc85xx_guts_freeze_timebase(device_t dev, bool freeze)
+{
+	struct mpc85xx_guts_softc *sc;
+	uint32_t devdisr;
+
+	sc = device_get_softc(dev);
+	
+	devdisr = bus_read_4(sc->sc_mem, GUTS_DEVDISR);
+	if (freeze)
+		bus_write_4(sc->sc_mem, GUTS_DEVDISR,
+		    devdisr | (DEVDISR_TB0 | DEVDISR_TB1));
+	else
+		bus_write_4(sc->sc_mem, GUTS_DEVDISR,
+		    devdisr & ~(DEVDISR_TB0 | DEVDISR_TB1));
+}
+
+static int
+mpc85xx_guts_probe(device_t dev)
+{
+	if (!ofw_bus_is_compatible(dev, "fsl,mpc8572-guts") &&
+	    !ofw_bus_is_compatible(dev, "fsl,p1020-guts") &&
+	    !ofw_bus_is_compatible(dev, "fsl,p1021-guts") &&
+	    !ofw_bus_is_compatible(dev, "fsl,p1022-guts") &&
+	    !ofw_bus_is_compatible(dev, "fsl,p1023-guts") &&
+	    !ofw_bus_is_compatible(dev, "fsl,p2020-guts"))
+		return (ENXIO);
+
+	device_set_desc(dev, "MPC85xx Global Utilities");
+	return (BUS_PROBE_GENERIC);
+}
+
+static int
+mpc85xx_guts_attach(device_t dev)
+{
+	struct mpc85xx_rcpm_softc *sc;
+	int rid;
+
+	sc = device_get_softc(dev);
+	freeze_timebase = mpc85xx_guts_freeze_timebase;
+	rcpm_dev = dev;
+
+	rid = 0;
+	sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+	    RF_ACTIVE | RF_SHAREABLE);
+
+	return (0);
+}
+
+static device_method_t mpc85xx_guts_methods[] = {
+	DEVMETHOD(device_probe,		mpc85xx_guts_probe),
+	DEVMETHOD(device_attach,	mpc85xx_guts_attach),
+	DEVMETHOD_END
+};
+
+static driver_t mpc85xx_guts_driver = {
+	"guts",
+	mpc85xx_guts_methods,
+	sizeof(struct mpc85xx_guts_softc)
+};
+
+static devclass_t mpc85xx_guts_devclass;
+
+EARLY_DRIVER_MODULE(mpc85xx_guts, simplebus, mpc85xx_guts_driver,
+	mpc85xx_guts_devclass, 0, 0, BUS_PASS_BUS);
diff --git a/freebsd/sys/powerpc/ofw/ofw_pcib_pci.c b/freebsd/sys/powerpc/ofw/ofw_pcib_pci.c
new file mode 100644
index 00000000..26dd52ba
--- /dev/null
+++ b/freebsd/sys/powerpc/ofw/ofw_pcib_pci.c
@@ -0,0 +1,178 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2000 BSDi
+ * All rights reserved.
+ *
+ * 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
+
+#include <machine/intr_machdep.h>
+
+#include <rtems/bsd/local/pcib_if.h>
+
+static int	ofw_pcib_pci_probe(device_t bus);
+static int	ofw_pcib_pci_attach(device_t bus);
+static phandle_t ofw_pcib_pci_get_node(device_t bus, device_t dev);
+static int	ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev,
+		    int intpin);
+
+static device_method_t ofw_pcib_pci_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		ofw_pcib_pci_probe),
+	DEVMETHOD(device_attach,	ofw_pcib_pci_attach),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_route_interrupt,	ofw_pcib_pci_route_interrupt),
+	DEVMETHOD(pcib_request_feature,	pcib_request_feature_allow),
+
+	/* ofw_bus interface */
+	DEVMETHOD(ofw_bus_get_node,	ofw_pcib_pci_get_node),
+
+	DEVMETHOD_END
+};
+
+static devclass_t pcib_devclass;
+
+struct ofw_pcib_softc {
+        /*
+         * This is here so that we can use pci bridge methods, too - the
+         * generic routines only need the dev, secbus and subbus members
+         * filled.
+         */
+        struct pcib_softc       ops_pcib_sc;
+	phandle_t		ops_node;
+        struct ofw_bus_iinfo    ops_iinfo;
+};
+
+DEFINE_CLASS_1(pcib, ofw_pcib_pci_driver, ofw_pcib_pci_methods,
+    sizeof(struct ofw_pcib_softc), pcib_driver);
+EARLY_DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_pci_driver, pcib_devclass, 0, 0,
+    BUS_PASS_BUS);
+
+static int
+ofw_pcib_pci_probe(device_t dev)
+{
+
+	if ((pci_get_class(dev) != PCIC_BRIDGE) ||
+	    (pci_get_subclass(dev) != PCIS_BRIDGE_PCI)) {
+		return (ENXIO);
+	}
+
+	if (ofw_bus_get_node(dev) == -1)
+		return (ENXIO);
+
+	device_set_desc(dev, "OFW PCI-PCI bridge");
+	return (0);
+}
+
+static int
+ofw_pcib_pci_attach(device_t dev)
+{
+	struct ofw_pcib_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->ops_pcib_sc.dev = dev;
+	sc->ops_node = ofw_bus_get_node(dev);
+
+	ofw_bus_setup_iinfo(sc->ops_node, &sc->ops_iinfo,
+	    sizeof(cell_t));
+
+	pcib_attach_common(dev);
+	return (pcib_attach_child(dev));
+}
+
+static phandle_t
+ofw_pcib_pci_get_node(device_t bridge, device_t dev)
+{
+	/* We have only one child, the PCI bus, so pass it our node */
+
+	return (ofw_bus_get_node(bridge));
+}
+
+static int
+ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, int intpin)
+{
+	struct ofw_pcib_softc *sc;
+	struct ofw_bus_iinfo *ii;
+	struct ofw_pci_register reg;
+	cell_t pintr, mintr[2];
+	int intrcells;
+	phandle_t iparent;
+
+	sc = device_get_softc(bridge);
+	ii = &sc->ops_iinfo;
+	if (ii->opi_imapsz > 0) {
+		pintr = intpin;
+
+		/* Fabricate imap information if this isn't an OFW device */
+		bzero(&reg, sizeof(reg));
+		reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
+		    (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
+		    (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
+
+		intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, &reg,
+		    sizeof(reg), &pintr, sizeof(pintr), mintr, sizeof(mintr),
+		    &iparent);
+		if (intrcells) {
+			/*
+			 * If we've found a mapping, return it and don't map
+			 * 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, intrcells,
+			    mintr);
+			return (mintr[0]);
+		}
+	} else if (intpin >= 1 && intpin <= 4) {
+		/*
+		 * When an interrupt map is missing, we need to do the
+		 * standard PCI swizzle and continue mapping at the parent.
+		 */
+		return (pcib_route_interrupt(bridge, dev, intpin));
+	}
+	return (PCIB_ROUTE_INTERRUPT(device_get_parent(device_get_parent(
+	    bridge)), bridge, intpin));
+}
+
-- 
2.35.3



More information about the devel mailing list