xref: /freebsd/sys/arm/mv/mv_pci.c (revision 6975124c23e9314a1e0eaa111cc0fe829ea102bd)
16975124cSRafal Jaworowski /*-
26975124cSRafal Jaworowski  * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
36975124cSRafal Jaworowski  * All rights reserved.
46975124cSRafal Jaworowski  *
56975124cSRafal Jaworowski  * Developed by Semihalf.
66975124cSRafal Jaworowski  *
76975124cSRafal Jaworowski  * Redistribution and use in source and binary forms, with or without
86975124cSRafal Jaworowski  * modification, are permitted provided that the following conditions
96975124cSRafal Jaworowski  * are met:
106975124cSRafal Jaworowski  * 1. Redistributions of source code must retain the above copyright
116975124cSRafal Jaworowski  *    notice, this list of conditions and the following disclaimer.
126975124cSRafal Jaworowski  * 2. Redistributions in binary form must reproduce the above copyright
136975124cSRafal Jaworowski  *    notice, this list of conditions and the following disclaimer in the
146975124cSRafal Jaworowski  *    documentation and/or other materials provided with the distribution.
156975124cSRafal Jaworowski  * 3. Neither the name of MARVELL nor the names of contributors
166975124cSRafal Jaworowski  *    may be used to endorse or promote products derived from this software
176975124cSRafal Jaworowski  *    without specific prior written permission.
186975124cSRafal Jaworowski  *
196975124cSRafal Jaworowski  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
206975124cSRafal Jaworowski  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
216975124cSRafal Jaworowski  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
226975124cSRafal Jaworowski  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
236975124cSRafal Jaworowski  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
246975124cSRafal Jaworowski  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
256975124cSRafal Jaworowski  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
266975124cSRafal Jaworowski  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
276975124cSRafal Jaworowski  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
286975124cSRafal Jaworowski  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
296975124cSRafal Jaworowski  * SUCH DAMAGE.
306975124cSRafal Jaworowski  */
316975124cSRafal Jaworowski 
326975124cSRafal Jaworowski /*
336975124cSRafal Jaworowski  * Marvell integrated PCI/PCI-Express controller driver.
346975124cSRafal Jaworowski  */
356975124cSRafal Jaworowski 
366975124cSRafal Jaworowski #include <sys/cdefs.h>
376975124cSRafal Jaworowski __FBSDID("$FreeBSD$");
386975124cSRafal Jaworowski 
396975124cSRafal Jaworowski #include <sys/param.h>
406975124cSRafal Jaworowski #include <sys/systm.h>
416975124cSRafal Jaworowski #include <sys/kernel.h>
426975124cSRafal Jaworowski #include <sys/lock.h>
436975124cSRafal Jaworowski #include <sys/malloc.h>
446975124cSRafal Jaworowski #include <sys/module.h>
456975124cSRafal Jaworowski #include <sys/mutex.h>
466975124cSRafal Jaworowski #include <sys/queue.h>
476975124cSRafal Jaworowski #include <sys/bus.h>
486975124cSRafal Jaworowski #include <sys/rman.h>
496975124cSRafal Jaworowski #include <sys/endian.h>
506975124cSRafal Jaworowski 
516975124cSRafal Jaworowski #include <vm/vm.h>
526975124cSRafal Jaworowski #include <vm/pmap.h>
536975124cSRafal Jaworowski 
546975124cSRafal Jaworowski #include <dev/pci/pcivar.h>
556975124cSRafal Jaworowski #include <dev/pci/pcireg.h>
566975124cSRafal Jaworowski #include <dev/pci/pcib_private.h>
576975124cSRafal Jaworowski 
586975124cSRafal Jaworowski #include "pcib_if.h"
596975124cSRafal Jaworowski 
606975124cSRafal Jaworowski #include <machine/resource.h>
616975124cSRafal Jaworowski #include <machine/bus.h>
626975124cSRafal Jaworowski 
636975124cSRafal Jaworowski #include <arm/mv/mvreg.h>
646975124cSRafal Jaworowski #include <arm/mv/mvvar.h>
656975124cSRafal Jaworowski 
666975124cSRafal Jaworowski #define PCI_CFG_ENA		(1 << 31)
676975124cSRafal Jaworowski #define PCI_CFG_BUS(bus)	(((bus) & 0xff) << 16)
686975124cSRafal Jaworowski #define PCI_CFG_DEV(dev)	(((dev) & 0x1f) << 11)
696975124cSRafal Jaworowski #define PCI_CFG_FUN(fun)	(((fun) & 0x7) << 8)
706975124cSRafal Jaworowski #define PCI_CFG_PCIE_REG(reg)	((reg) & 0xfc)
716975124cSRafal Jaworowski 
726975124cSRafal Jaworowski #define PCI_REG_CFG_ADDR	0x0C78
736975124cSRafal Jaworowski #define PCI_REG_CFG_DATA	0x0C7C
746975124cSRafal Jaworowski #define PCI_REG_P2P_CONF	0x1D14
756975124cSRafal Jaworowski 
766975124cSRafal Jaworowski #define PCIE_REG_CFG_ADDR	0x18F8
776975124cSRafal Jaworowski #define PCIE_REG_CFG_DATA	0x18FC
786975124cSRafal Jaworowski #define PCIE_REG_CONTROL	0x1A00
796975124cSRafal Jaworowski #define   PCIE_CTRL_LINK1X	0x00000001
806975124cSRafal Jaworowski #define PCIE_REG_STATUS		0x1A04
816975124cSRafal Jaworowski #define PCIE_REG_IRQ_MASK	0x1910
826975124cSRafal Jaworowski 
836975124cSRafal Jaworowski #define STATUS_BUS_OFFS		8
846975124cSRafal Jaworowski #define STATUS_BUS_MASK		(0xFF << STATUS_BUS_OFFS)
856975124cSRafal Jaworowski #define STATUS_DEV_OFFS		16
866975124cSRafal Jaworowski #define STATUS_DEV_MASK		(0x1F << STATUS_DEV_OFFS)
876975124cSRafal Jaworowski 
886975124cSRafal Jaworowski #define P2P_CONF_BUS_OFFS	16
896975124cSRafal Jaworowski #define P2P_CONF_BUS_MASK	(0xFF << P2P_CONF_BUS_OFFS)
906975124cSRafal Jaworowski #define P2P_CONF_DEV_OFFS	24
916975124cSRafal Jaworowski #define P2P_CONF_DEV_MASK	(0x1F << P2P_CONF_DEV_OFFS)
926975124cSRafal Jaworowski 
936975124cSRafal Jaworowski #define PCI_VENDORID_MRVL	0x11AB
946975124cSRafal Jaworowski 
956975124cSRafal Jaworowski struct pcib_mbus_softc {
966975124cSRafal Jaworowski 	device_t	sc_dev;
976975124cSRafal Jaworowski 
986975124cSRafal Jaworowski 	bus_addr_t	sc_iomem_base;
996975124cSRafal Jaworowski 	bus_addr_t	sc_iomem_size;
1006975124cSRafal Jaworowski 	bus_addr_t	sc_iomem_alloc;		/* Next allocation. */
1016975124cSRafal Jaworowski 
1026975124cSRafal Jaworowski 	bus_addr_t	sc_ioport_base;
1036975124cSRafal Jaworowski 	bus_addr_t	sc_ioport_size;
1046975124cSRafal Jaworowski 	bus_addr_t	sc_ioport_alloc;	/* Next allocation. */
1056975124cSRafal Jaworowski 
1066975124cSRafal Jaworowski 	struct resource	*sc_res;
1076975124cSRafal Jaworowski 	bus_space_handle_t sc_bsh;
1086975124cSRafal Jaworowski 	bus_space_tag_t	sc_bst;
1096975124cSRafal Jaworowski 	int		sc_rid;
1106975124cSRafal Jaworowski 
1116975124cSRafal Jaworowski 	int		sc_busnr;		/* Host bridge bus number */
1126975124cSRafal Jaworowski 	int		sc_devnr;		/* Host bridge device number */
1136975124cSRafal Jaworowski 
1146975124cSRafal Jaworowski 	const struct obio_pci *sc_info;
1156975124cSRafal Jaworowski };
1166975124cSRafal Jaworowski 
1176975124cSRafal Jaworowski static void pcib_mbus_identify(driver_t *driver, device_t parent);
1186975124cSRafal Jaworowski static int pcib_mbus_probe(device_t);
1196975124cSRafal Jaworowski static int pcib_mbus_attach(device_t);
1206975124cSRafal Jaworowski 
1216975124cSRafal Jaworowski static struct resource *pcib_mbus_alloc_resource(device_t, device_t, int, int *,
1226975124cSRafal Jaworowski     u_long, u_long, u_long, u_int);
1236975124cSRafal Jaworowski static int pcib_mbus_release_resource(device_t, device_t, int, int,
1246975124cSRafal Jaworowski     struct resource *);
1256975124cSRafal Jaworowski static int pcib_mbus_read_ivar(device_t, device_t, int, uintptr_t *);
1266975124cSRafal Jaworowski static int pcib_mbus_write_ivar(device_t, device_t, int, uintptr_t);
1276975124cSRafal Jaworowski 
1286975124cSRafal Jaworowski static int pcib_mbus_maxslots(device_t);
1296975124cSRafal Jaworowski static uint32_t pcib_mbus_read_config(device_t, u_int, u_int, u_int, u_int,
1306975124cSRafal Jaworowski     int);
1316975124cSRafal Jaworowski static void pcib_mbus_write_config(device_t, u_int, u_int, u_int, u_int,
1326975124cSRafal Jaworowski     uint32_t, int);
1336975124cSRafal Jaworowski static int pcib_mbus_init(struct pcib_mbus_softc *sc, int bus, int maxslot);
1346975124cSRafal Jaworowski static int pcib_mbus_init_bar(struct pcib_mbus_softc *sc, int bus, int slot,
1356975124cSRafal Jaworowski     int func, int barno);
1366975124cSRafal Jaworowski static void pcib_mbus_init_bridge(struct pcib_mbus_softc *sc, int bus, int slot,
1376975124cSRafal Jaworowski     int func);
1386975124cSRafal Jaworowski static int pcib_mbus_init_resources(struct pcib_mbus_softc *sc, int bus,
1396975124cSRafal Jaworowski     int slot, int func, int hdrtype);
1406975124cSRafal Jaworowski 
1416975124cSRafal Jaworowski /*
1426975124cSRafal Jaworowski  * Bus interface definitions.
1436975124cSRafal Jaworowski  */
1446975124cSRafal Jaworowski static device_method_t pcib_mbus_methods[] = {
1456975124cSRafal Jaworowski 	/* Device interface */
1466975124cSRafal Jaworowski 	DEVMETHOD(device_identify,		pcib_mbus_identify),
1476975124cSRafal Jaworowski 	DEVMETHOD(device_probe,			pcib_mbus_probe),
1486975124cSRafal Jaworowski 	DEVMETHOD(device_attach,		pcib_mbus_attach),
1496975124cSRafal Jaworowski 
1506975124cSRafal Jaworowski 	/* Bus interface */
1516975124cSRafal Jaworowski 	DEVMETHOD(bus_print_child,		bus_generic_print_child),
1526975124cSRafal Jaworowski 	DEVMETHOD(bus_read_ivar,		pcib_mbus_read_ivar),
1536975124cSRafal Jaworowski 	DEVMETHOD(bus_write_ivar,		pcib_mbus_write_ivar),
1546975124cSRafal Jaworowski 	DEVMETHOD(bus_alloc_resource,		pcib_mbus_alloc_resource),
1556975124cSRafal Jaworowski 	DEVMETHOD(bus_release_resource,		pcib_mbus_release_resource),
1566975124cSRafal Jaworowski 	DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
1576975124cSRafal Jaworowski 	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
1586975124cSRafal Jaworowski 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
1596975124cSRafal Jaworowski 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
1606975124cSRafal Jaworowski 
1616975124cSRafal Jaworowski 	/* pcib interface */
1626975124cSRafal Jaworowski 	DEVMETHOD(pcib_maxslots,		pcib_mbus_maxslots),
1636975124cSRafal Jaworowski 	DEVMETHOD(pcib_read_config,		pcib_mbus_read_config),
1646975124cSRafal Jaworowski 	DEVMETHOD(pcib_write_config,		pcib_mbus_write_config),
1656975124cSRafal Jaworowski 	DEVMETHOD(pcib_route_interrupt,		pcib_route_interrupt),
1666975124cSRafal Jaworowski 
1676975124cSRafal Jaworowski 	{ 0, 0 }
1686975124cSRafal Jaworowski };
1696975124cSRafal Jaworowski 
1706975124cSRafal Jaworowski static driver_t pcib_mbus_driver = {
1716975124cSRafal Jaworowski 	"pcib",
1726975124cSRafal Jaworowski 	pcib_mbus_methods,
1736975124cSRafal Jaworowski 	sizeof(struct pcib_mbus_softc),
1746975124cSRafal Jaworowski };
1756975124cSRafal Jaworowski 
1766975124cSRafal Jaworowski devclass_t pcib_devclass;
1776975124cSRafal Jaworowski 
1786975124cSRafal Jaworowski DRIVER_MODULE(pcib, mbus, pcib_mbus_driver, pcib_devclass, 0, 0);
1796975124cSRafal Jaworowski 
1806975124cSRafal Jaworowski static struct mtx pcicfg_mtx;
1816975124cSRafal Jaworowski 
1826975124cSRafal Jaworowski static inline void
1836975124cSRafal Jaworowski pcib_write_irq_mask(struct pcib_mbus_softc *sc, uint32_t mask)
1846975124cSRafal Jaworowski {
1856975124cSRafal Jaworowski 
1866975124cSRafal Jaworowski 	if (!sc->sc_info->op_type != MV_TYPE_PCI)
1876975124cSRafal Jaworowski 		return;
1886975124cSRafal Jaworowski 
1896975124cSRafal Jaworowski 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
1906975124cSRafal Jaworowski 	    PCIE_REG_IRQ_MASK, mask);
1916975124cSRafal Jaworowski }
1926975124cSRafal Jaworowski 
1936975124cSRafal Jaworowski static void
1946975124cSRafal Jaworowski pcib_mbus_hw_cfginit(void)
1956975124cSRafal Jaworowski {
1966975124cSRafal Jaworowski 	static int opened = 0;
1976975124cSRafal Jaworowski 
1986975124cSRafal Jaworowski 	if (opened)
1996975124cSRafal Jaworowski 		return;
2006975124cSRafal Jaworowski 
2016975124cSRafal Jaworowski 	mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
2026975124cSRafal Jaworowski 	opened = 1;
2036975124cSRafal Jaworowski }
2046975124cSRafal Jaworowski 
2056975124cSRafal Jaworowski static uint32_t
2066975124cSRafal Jaworowski pcib_mbus_hw_cfgread(struct pcib_mbus_softc *sc, u_int bus, u_int slot,
2076975124cSRafal Jaworowski     u_int func, u_int reg, int bytes)
2086975124cSRafal Jaworowski {
2096975124cSRafal Jaworowski 	uint32_t addr, data, ca, cd;
2106975124cSRafal Jaworowski 
2116975124cSRafal Jaworowski 	ca = (sc->sc_info->op_type != MV_TYPE_PCI) ?
2126975124cSRafal Jaworowski 	    PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR;
2136975124cSRafal Jaworowski 	cd = (sc->sc_info->op_type != MV_TYPE_PCI) ?
2146975124cSRafal Jaworowski 	    PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA;
2156975124cSRafal Jaworowski 	addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) |
2166975124cSRafal Jaworowski 	    PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg);
2176975124cSRafal Jaworowski 
2186975124cSRafal Jaworowski 	mtx_lock_spin(&pcicfg_mtx);
2196975124cSRafal Jaworowski 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr);
2206975124cSRafal Jaworowski 
2216975124cSRafal Jaworowski 	data = ~0;
2226975124cSRafal Jaworowski 	switch (bytes) {
2236975124cSRafal Jaworowski 	case 1:
2246975124cSRafal Jaworowski 		data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
2256975124cSRafal Jaworowski 		    cd + (reg & 3));
2266975124cSRafal Jaworowski 		break;
2276975124cSRafal Jaworowski 	case 2:
2286975124cSRafal Jaworowski 		data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh,
2296975124cSRafal Jaworowski 		    cd + (reg & 2)));
2306975124cSRafal Jaworowski 		break;
2316975124cSRafal Jaworowski 	case 4:
2326975124cSRafal Jaworowski 		data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
2336975124cSRafal Jaworowski 		    cd));
2346975124cSRafal Jaworowski 		break;
2356975124cSRafal Jaworowski 	}
2366975124cSRafal Jaworowski 	mtx_unlock_spin(&pcicfg_mtx);
2376975124cSRafal Jaworowski 	return (data);
2386975124cSRafal Jaworowski }
2396975124cSRafal Jaworowski 
2406975124cSRafal Jaworowski static void
2416975124cSRafal Jaworowski pcib_mbus_hw_cfgwrite(struct pcib_mbus_softc *sc, u_int bus, u_int slot,
2426975124cSRafal Jaworowski     u_int func, u_int reg, uint32_t data, int bytes)
2436975124cSRafal Jaworowski {
2446975124cSRafal Jaworowski 	uint32_t addr, ca, cd;
2456975124cSRafal Jaworowski 
2466975124cSRafal Jaworowski 	ca = (sc->sc_info->op_type != MV_TYPE_PCI) ?
2476975124cSRafal Jaworowski 	    PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR;
2486975124cSRafal Jaworowski 	cd = (sc->sc_info->op_type != MV_TYPE_PCI) ?
2496975124cSRafal Jaworowski 	    PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA;
2506975124cSRafal Jaworowski 	addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) |
2516975124cSRafal Jaworowski 	    PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg);
2526975124cSRafal Jaworowski 
2536975124cSRafal Jaworowski 	mtx_lock_spin(&pcicfg_mtx);
2546975124cSRafal Jaworowski 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr);
2556975124cSRafal Jaworowski 
2566975124cSRafal Jaworowski 	switch (bytes) {
2576975124cSRafal Jaworowski 	case 1:
2586975124cSRafal Jaworowski 		bus_space_write_1(sc->sc_bst, sc->sc_bsh,
2596975124cSRafal Jaworowski 		    cd + (reg & 3), data);
2606975124cSRafal Jaworowski 		break;
2616975124cSRafal Jaworowski 	case 2:
2626975124cSRafal Jaworowski 		bus_space_write_2(sc->sc_bst, sc->sc_bsh,
2636975124cSRafal Jaworowski 		    cd + (reg & 2), htole16(data));
2646975124cSRafal Jaworowski 		break;
2656975124cSRafal Jaworowski 	case 4:
2666975124cSRafal Jaworowski 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
2676975124cSRafal Jaworowski 		    cd, htole32(data));
2686975124cSRafal Jaworowski 		break;
2696975124cSRafal Jaworowski 	}
2706975124cSRafal Jaworowski 	mtx_unlock_spin(&pcicfg_mtx);
2716975124cSRafal Jaworowski }
2726975124cSRafal Jaworowski 
2736975124cSRafal Jaworowski static int
2746975124cSRafal Jaworowski pcib_mbus_maxslots(device_t dev)
2756975124cSRafal Jaworowski {
2766975124cSRafal Jaworowski 	struct pcib_mbus_softc *sc = device_get_softc(dev);
2776975124cSRafal Jaworowski 
2786975124cSRafal Jaworowski 	return ((sc->sc_info->op_type != MV_TYPE_PCI) ? 1 : PCI_SLOTMAX);
2796975124cSRafal Jaworowski }
2806975124cSRafal Jaworowski 
2816975124cSRafal Jaworowski static uint32_t
2826975124cSRafal Jaworowski pcib_mbus_read_config(device_t dev, u_int bus, u_int slot, u_int func,
2836975124cSRafal Jaworowski     u_int reg, int bytes)
2846975124cSRafal Jaworowski {
2856975124cSRafal Jaworowski 	struct pcib_mbus_softc *sc = device_get_softc(dev);
2866975124cSRafal Jaworowski 
2876975124cSRafal Jaworowski 	/* Skip self */
2886975124cSRafal Jaworowski 	if (bus == sc->sc_busnr && slot == sc->sc_devnr)
2896975124cSRafal Jaworowski 		return (~0U);
2906975124cSRafal Jaworowski 
2916975124cSRafal Jaworowski 	return (pcib_mbus_hw_cfgread(sc, bus, slot, func, reg, bytes));
2926975124cSRafal Jaworowski }
2936975124cSRafal Jaworowski 
2946975124cSRafal Jaworowski static void
2956975124cSRafal Jaworowski pcib_mbus_write_config(device_t dev, u_int bus, u_int slot, u_int func,
2966975124cSRafal Jaworowski     u_int reg, uint32_t val, int bytes)
2976975124cSRafal Jaworowski {
2986975124cSRafal Jaworowski 	struct pcib_mbus_softc *sc = device_get_softc(dev);
2996975124cSRafal Jaworowski 
3006975124cSRafal Jaworowski 	/* Skip self */
3016975124cSRafal Jaworowski 	if (bus == sc->sc_busnr && slot == sc->sc_devnr)
3026975124cSRafal Jaworowski 		return;
3036975124cSRafal Jaworowski 
3046975124cSRafal Jaworowski 	pcib_mbus_hw_cfgwrite(sc, bus, slot, func, reg, val, bytes);
3056975124cSRafal Jaworowski }
3066975124cSRafal Jaworowski 
3076975124cSRafal Jaworowski static void
3086975124cSRafal Jaworowski pcib_mbus_add_child(driver_t *driver, device_t parent, struct pcib_mbus_softc *sc)
3096975124cSRafal Jaworowski {
3106975124cSRafal Jaworowski 	device_t child;
3116975124cSRafal Jaworowski 	int error;
3126975124cSRafal Jaworowski 
3136975124cSRafal Jaworowski 	/* Configure CPU decoding windows */
3146975124cSRafal Jaworowski 	error = decode_win_cpu_set(sc->sc_info->op_io_win_target,
3156975124cSRafal Jaworowski 	    sc->sc_info->op_io_win_attr, sc->sc_info->op_io_base,
3166975124cSRafal Jaworowski 	    sc->sc_info->op_io_size, -1);
3176975124cSRafal Jaworowski 	if (error < 0) {
3186975124cSRafal Jaworowski 		device_printf(parent, "Could not set up CPU decode "
3196975124cSRafal Jaworowski 		    "window for PCI IO\n");
3206975124cSRafal Jaworowski 		return;
3216975124cSRafal Jaworowski 	}
3226975124cSRafal Jaworowski 	error = decode_win_cpu_set(sc->sc_info->op_mem_win_target,
3236975124cSRafal Jaworowski 	    sc->sc_info->op_mem_win_attr, sc->sc_info->op_mem_base,
3246975124cSRafal Jaworowski 	    sc->sc_info->op_mem_size, -1);
3256975124cSRafal Jaworowski 	if (error < 0) {
3266975124cSRafal Jaworowski 		device_printf(parent, "Could not set up CPU decode "
3276975124cSRafal Jaworowski 		    "windows for PCI MEM\n");
3286975124cSRafal Jaworowski 		return;
3296975124cSRafal Jaworowski 	}
3306975124cSRafal Jaworowski 
3316975124cSRafal Jaworowski 	/* Create driver instance */
3326975124cSRafal Jaworowski 	child = BUS_ADD_CHILD(parent, 0, driver->name, -1);
3336975124cSRafal Jaworowski 	bus_set_resource(child, SYS_RES_MEMORY, 0,
3346975124cSRafal Jaworowski 	    sc->sc_info->op_base, sc->sc_info->op_size);
3356975124cSRafal Jaworowski 	device_set_softc(child, sc);
3366975124cSRafal Jaworowski }
3376975124cSRafal Jaworowski 
3386975124cSRafal Jaworowski static void
3396975124cSRafal Jaworowski pcib_mbus_identify(driver_t *driver, device_t parent)
3406975124cSRafal Jaworowski {
3416975124cSRafal Jaworowski 	const struct obio_pci *info = mv_pci_info;
3426975124cSRafal Jaworowski 	struct pcib_mbus_softc *sc;
3436975124cSRafal Jaworowski 	uint32_t control;
3446975124cSRafal Jaworowski 
3456975124cSRafal Jaworowski 	while (info->op_base) {
3466975124cSRafal Jaworowski 		sc = malloc(driver->size, M_DEVBUF, M_NOWAIT | M_ZERO);
3476975124cSRafal Jaworowski 		if (sc == NULL) {
3486975124cSRafal Jaworowski 			device_printf(parent, "Could not allocate pcib "
3496975124cSRafal Jaworowski 			    "memory\n");
3506975124cSRafal Jaworowski 			break;
3516975124cSRafal Jaworowski 		}
3526975124cSRafal Jaworowski 		sc->sc_info = info++;
3536975124cSRafal Jaworowski 
3546975124cSRafal Jaworowski 		/*
3556975124cSRafal Jaworowski 		 * PCI bridge objects are instantiated immediately. PCI-Express
3566975124cSRafal Jaworowski 		 * bridges require more complicated handling depending on
3576975124cSRafal Jaworowski 		 * platform configuration.
3586975124cSRafal Jaworowski 		 */
3596975124cSRafal Jaworowski 		if (sc->sc_info->op_type == MV_TYPE_PCI) {
3606975124cSRafal Jaworowski 			pcib_mbus_add_child(driver, parent, sc);
3616975124cSRafal Jaworowski 			continue;
3626975124cSRafal Jaworowski 		}
3636975124cSRafal Jaworowski 
3646975124cSRafal Jaworowski 		/*
3656975124cSRafal Jaworowski 		 * Read link configuration
3666975124cSRafal Jaworowski 		 */
3676975124cSRafal Jaworowski 		sc->sc_rid = 0;
3686975124cSRafal Jaworowski 		sc->sc_res = BUS_ALLOC_RESOURCE(parent, parent, SYS_RES_MEMORY,
3696975124cSRafal Jaworowski 		    &sc->sc_rid, sc->sc_info->op_base, sc->sc_info->op_base +
3706975124cSRafal Jaworowski 		    sc->sc_info->op_size - 1, sc->sc_info->op_size,
3716975124cSRafal Jaworowski 		    RF_ACTIVE);
3726975124cSRafal Jaworowski 		if (sc->sc_res == NULL)
3736975124cSRafal Jaworowski 			device_printf(parent, "Could not map pcib memory\n");
3746975124cSRafal Jaworowski 
3756975124cSRafal Jaworowski 		sc->sc_bst = rman_get_bustag(sc->sc_res);
3766975124cSRafal Jaworowski 		sc->sc_bsh = rman_get_bushandle(sc->sc_res);
3776975124cSRafal Jaworowski 
3786975124cSRafal Jaworowski 		control = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
3796975124cSRafal Jaworowski 		    PCIE_REG_CONTROL);
3806975124cSRafal Jaworowski 
3816975124cSRafal Jaworowski 		BUS_RELEASE_RESOURCE(parent, parent, SYS_RES_MEMORY, sc->sc_rid,
3826975124cSRafal Jaworowski 		    sc->sc_res);
3836975124cSRafal Jaworowski 
3846975124cSRafal Jaworowski 		/*
3856975124cSRafal Jaworowski 		 * If this PCI-E port (controller) is configured (by the
3866975124cSRafal Jaworowski 		 * underlying firmware) with lane width other than 1x, there
3876975124cSRafal Jaworowski 		 * are auxiliary resources defined for aggregating more width
3886975124cSRafal Jaworowski 		 * on our lane. Skip all such entries as they are not
3896975124cSRafal Jaworowski 		 * standalone ports and must not have a device object
3906975124cSRafal Jaworowski 		 * instantiated.
3916975124cSRafal Jaworowski 		 */
3926975124cSRafal Jaworowski 		if ((control & PCIE_CTRL_LINK1X) == 0)
3936975124cSRafal Jaworowski 			while (info->op_base &&
3946975124cSRafal Jaworowski 			    info->op_type == MV_TYPE_PCIE_AGGR_LANE)
3956975124cSRafal Jaworowski 				info++;
3966975124cSRafal Jaworowski 
3976975124cSRafal Jaworowski 		pcib_mbus_add_child(driver, parent, sc);
3986975124cSRafal Jaworowski 	}
3996975124cSRafal Jaworowski }
4006975124cSRafal Jaworowski 
4016975124cSRafal Jaworowski static int
4026975124cSRafal Jaworowski pcib_mbus_probe(device_t self)
4036975124cSRafal Jaworowski {
4046975124cSRafal Jaworowski 	char buf[128];
4056975124cSRafal Jaworowski 	struct pcib_mbus_softc *sc;
4066975124cSRafal Jaworowski 	const char *id, *type;
4076975124cSRafal Jaworowski 	uint32_t val;
4086975124cSRafal Jaworowski 	int rv = ENOENT, bus, dev;
4096975124cSRafal Jaworowski 
4106975124cSRafal Jaworowski 	sc = device_get_softc(self);
4116975124cSRafal Jaworowski 
4126975124cSRafal Jaworowski 	sc->sc_rid = 0;
4136975124cSRafal Jaworowski 	sc->sc_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &sc->sc_rid,
4146975124cSRafal Jaworowski 	    RF_ACTIVE);
4156975124cSRafal Jaworowski 	if (sc->sc_res == NULL) {
4166975124cSRafal Jaworowski 		device_printf(self, "Could not map memory\n");
4176975124cSRafal Jaworowski 		return (ENXIO);
4186975124cSRafal Jaworowski 	}
4196975124cSRafal Jaworowski 
4206975124cSRafal Jaworowski 	sc->sc_bst = rman_get_bustag(sc->sc_res);
4216975124cSRafal Jaworowski 	sc->sc_bsh = rman_get_bushandle(sc->sc_res);
4226975124cSRafal Jaworowski 
4236975124cSRafal Jaworowski 	pcib_mbus_hw_cfginit();
4246975124cSRafal Jaworowski 
4256975124cSRafal Jaworowski 	/* Retrieve configuration of the bridge */
4266975124cSRafal Jaworowski 	if (sc->sc_info->op_type == MV_TYPE_PCI) {
4276975124cSRafal Jaworowski 		val = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
4286975124cSRafal Jaworowski 		    PCI_REG_P2P_CONF);
4296975124cSRafal Jaworowski 		bus = sc->sc_busnr = (val & P2P_CONF_BUS_MASK) >>
4306975124cSRafal Jaworowski 		    P2P_CONF_BUS_OFFS;
4316975124cSRafal Jaworowski 		dev = sc->sc_devnr = (val & P2P_CONF_DEV_MASK) >>
4326975124cSRafal Jaworowski 		    P2P_CONF_DEV_OFFS;
4336975124cSRafal Jaworowski 	} else {
4346975124cSRafal Jaworowski 		val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_STATUS);
4356975124cSRafal Jaworowski 		bus = sc->sc_busnr = (val & STATUS_BUS_MASK) >> STATUS_BUS_OFFS;
4366975124cSRafal Jaworowski 		dev = sc->sc_devnr = (val & STATUS_DEV_MASK) >> STATUS_DEV_OFFS;
4376975124cSRafal Jaworowski 	}
4386975124cSRafal Jaworowski 
4396975124cSRafal Jaworowski 	val = pcib_mbus_hw_cfgread(sc, bus, dev, 0, PCIR_VENDOR, 2);
4406975124cSRafal Jaworowski 	if (val != PCI_VENDORID_MRVL)
4416975124cSRafal Jaworowski 		goto out;
4426975124cSRafal Jaworowski 
4436975124cSRafal Jaworowski 	val = pcib_mbus_hw_cfgread(sc, bus, dev, 0, PCIR_DEVICE, 2);
4446975124cSRafal Jaworowski 	switch (val) {
4456975124cSRafal Jaworowski 	case 0x5281:
4466975124cSRafal Jaworowski 		id = "88F5281";
4476975124cSRafal Jaworowski 		break;
4486975124cSRafal Jaworowski 	case 0x5182:
4496975124cSRafal Jaworowski 		id = "88F5182";
4506975124cSRafal Jaworowski 		break;
4516975124cSRafal Jaworowski 	case 0x6281:
4526975124cSRafal Jaworowski 		id = "88F6281";
4536975124cSRafal Jaworowski 		break;
4546975124cSRafal Jaworowski 	case 0x6381:
4556975124cSRafal Jaworowski 		id = "MV78100";
4566975124cSRafal Jaworowski 		break;
4576975124cSRafal Jaworowski 	default:
4586975124cSRafal Jaworowski 		device_printf(self, "unknown Marvell PCI bridge: %x\n", val);
4596975124cSRafal Jaworowski 		goto out;
4606975124cSRafal Jaworowski 	}
4616975124cSRafal Jaworowski 
4626975124cSRafal Jaworowski 	type = "PCI";
4636975124cSRafal Jaworowski 	val = pcib_mbus_hw_cfgread(sc, bus, dev, 0, PCIR_CAP_PTR, 1);
4646975124cSRafal Jaworowski 	while (val != 0) {
4656975124cSRafal Jaworowski 		val = pcib_mbus_hw_cfgread(sc, bus, dev, 0, val, 2);
4666975124cSRafal Jaworowski 		switch (val & 0xff) {
4676975124cSRafal Jaworowski 		case PCIY_PCIX:
4686975124cSRafal Jaworowski 			type = "PCI-X";
4696975124cSRafal Jaworowski 			break;
4706975124cSRafal Jaworowski 		case PCIY_EXPRESS:
4716975124cSRafal Jaworowski 			type = "PCI-Express";
4726975124cSRafal Jaworowski 			break;
4736975124cSRafal Jaworowski 		}
4746975124cSRafal Jaworowski 		val = (val >> 8) & 0xff;
4756975124cSRafal Jaworowski 	}
4766975124cSRafal Jaworowski 
4776975124cSRafal Jaworowski 	snprintf(buf, sizeof(buf), "Marvell %s %s host controller", id,
4786975124cSRafal Jaworowski 	    type);
4796975124cSRafal Jaworowski 	device_set_desc_copy(self, buf);
4806975124cSRafal Jaworowski 	rv = BUS_PROBE_DEFAULT;
4816975124cSRafal Jaworowski out:
4826975124cSRafal Jaworowski 	bus_release_resource(self, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
4836975124cSRafal Jaworowski 	return (rv);
4846975124cSRafal Jaworowski }
4856975124cSRafal Jaworowski 
4866975124cSRafal Jaworowski static int
4876975124cSRafal Jaworowski pcib_mbus_attach(device_t self)
4886975124cSRafal Jaworowski {
4896975124cSRafal Jaworowski 	struct pcib_mbus_softc *sc;
4906975124cSRafal Jaworowski 	uint32_t val;
4916975124cSRafal Jaworowski 	int err;
4926975124cSRafal Jaworowski 
4936975124cSRafal Jaworowski 	sc = device_get_softc(self);
4946975124cSRafal Jaworowski 	sc->sc_dev = self;
4956975124cSRafal Jaworowski 
4966975124cSRafal Jaworowski 	sc->sc_rid = 0;
4976975124cSRafal Jaworowski 	sc->sc_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &sc->sc_rid,
4986975124cSRafal Jaworowski 	    RF_ACTIVE);
4996975124cSRafal Jaworowski 	if (sc->sc_res == NULL) {
5006975124cSRafal Jaworowski 		device_printf(self, "Could not map memory\n");
5016975124cSRafal Jaworowski 		return (ENXIO);
5026975124cSRafal Jaworowski 	}
5036975124cSRafal Jaworowski 	sc->sc_bst = rman_get_bustag(sc->sc_res);
5046975124cSRafal Jaworowski 	sc->sc_bsh = rman_get_bushandle(sc->sc_res);
5056975124cSRafal Jaworowski 
5066975124cSRafal Jaworowski 	/* Enable PCI bridge */
5076975124cSRafal Jaworowski 	val = pcib_mbus_hw_cfgread(sc, sc->sc_busnr, sc->sc_devnr, 0,
5086975124cSRafal Jaworowski 	    PCIR_COMMAND, 2);
5096975124cSRafal Jaworowski 	val |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
5106975124cSRafal Jaworowski 	    PCIM_CMD_PORTEN;
5116975124cSRafal Jaworowski 	pcib_mbus_hw_cfgwrite(sc, sc->sc_busnr, sc->sc_devnr, 0,
5126975124cSRafal Jaworowski 	    PCIR_COMMAND, val, 2);
5136975124cSRafal Jaworowski 
5146975124cSRafal Jaworowski 	sc->sc_iomem_base = sc->sc_info->op_mem_base;
5156975124cSRafal Jaworowski 	sc->sc_iomem_size = sc->sc_info->op_mem_size;
5166975124cSRafal Jaworowski 	sc->sc_iomem_alloc = sc->sc_info->op_mem_base;
5176975124cSRafal Jaworowski 
5186975124cSRafal Jaworowski 	sc->sc_ioport_base = sc->sc_info->op_io_base;
5196975124cSRafal Jaworowski 	sc->sc_ioport_size = sc->sc_info->op_io_size;
5206975124cSRafal Jaworowski 	sc->sc_ioport_alloc = sc->sc_info->op_io_base;
5216975124cSRafal Jaworowski 
5226975124cSRafal Jaworowski 	err = pcib_mbus_init(sc, sc->sc_busnr, pcib_mbus_maxslots(sc->sc_dev));
5236975124cSRafal Jaworowski 	if (err)
5246975124cSRafal Jaworowski 		return(err);
5256975124cSRafal Jaworowski 
5266975124cSRafal Jaworowski 	device_add_child(self, "pci", -1);
5276975124cSRafal Jaworowski 	return (bus_generic_attach(self));
5286975124cSRafal Jaworowski }
5296975124cSRafal Jaworowski 
5306975124cSRafal Jaworowski static int
5316975124cSRafal Jaworowski pcib_mbus_init_bar(struct pcib_mbus_softc *sc, int bus, int slot, int func,
5326975124cSRafal Jaworowski     int barno)
5336975124cSRafal Jaworowski {
5346975124cSRafal Jaworowski 	bus_addr_t *allocp, limit;
5356975124cSRafal Jaworowski 	uint32_t addr, bar, mask, size;
5366975124cSRafal Jaworowski 	int reg, width;
5376975124cSRafal Jaworowski 
5386975124cSRafal Jaworowski 	reg = PCIR_BAR(barno);
5396975124cSRafal Jaworowski 	bar = pcib_mbus_read_config(sc->sc_dev, bus, slot, func, reg, 4);
5406975124cSRafal Jaworowski 	if (bar == 0)
5416975124cSRafal Jaworowski 		return (1);
5426975124cSRafal Jaworowski 
5436975124cSRafal Jaworowski 	/* Calculate BAR size: 64 or 32 bit (in 32-bit units) */
5446975124cSRafal Jaworowski 	width = ((bar & 7) == 4) ? 2 : 1;
5456975124cSRafal Jaworowski 
5466975124cSRafal Jaworowski 	pcib_mbus_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4);
5476975124cSRafal Jaworowski 	size = pcib_mbus_read_config(sc->sc_dev, bus, slot, func, reg, 4);
5486975124cSRafal Jaworowski 
5496975124cSRafal Jaworowski 	/* Get BAR type and size */
5506975124cSRafal Jaworowski 	if (bar & 1) {
5516975124cSRafal Jaworowski 		/* I/O port */
5526975124cSRafal Jaworowski 		allocp = &sc->sc_ioport_alloc;
5536975124cSRafal Jaworowski 		limit = sc->sc_ioport_base + sc->sc_ioport_size;
5546975124cSRafal Jaworowski 		size &= ~0x3;
5556975124cSRafal Jaworowski 		if ((size & 0xffff0000) == 0)
5566975124cSRafal Jaworowski 			size |= 0xffff0000;
5576975124cSRafal Jaworowski 	} else {
5586975124cSRafal Jaworowski 		/* Memory */
5596975124cSRafal Jaworowski 		allocp = &sc->sc_iomem_alloc;
5606975124cSRafal Jaworowski 		limit = sc->sc_iomem_base + sc->sc_iomem_size;
5616975124cSRafal Jaworowski 		size &= ~0xF;
5626975124cSRafal Jaworowski 	}
5636975124cSRafal Jaworowski 	mask = ~size;
5646975124cSRafal Jaworowski 	size = mask + 1;
5656975124cSRafal Jaworowski 
5666975124cSRafal Jaworowski 	/* Sanity check (must be a power of 2) */
5676975124cSRafal Jaworowski 	if (size & mask)
5686975124cSRafal Jaworowski 		return (width);
5696975124cSRafal Jaworowski 
5706975124cSRafal Jaworowski 	addr = (*allocp + mask) & ~mask;
5716975124cSRafal Jaworowski 	if ((*allocp = addr + size) >= limit)
5726975124cSRafal Jaworowski 		return (-1);
5736975124cSRafal Jaworowski 
5746975124cSRafal Jaworowski 	if (bootverbose)
5756975124cSRafal Jaworowski 		printf("PCI %u:%u:%u: reg %x: size=%08x: addr=%08x\n",
5766975124cSRafal Jaworowski 		    bus, slot, func, reg, size, addr);
5776975124cSRafal Jaworowski 
5786975124cSRafal Jaworowski 	pcib_mbus_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
5796975124cSRafal Jaworowski 	if (width == 2)
5806975124cSRafal Jaworowski 		pcib_mbus_write_config(sc->sc_dev, bus, slot, func, reg + 4,
5816975124cSRafal Jaworowski 		    0, 4);
5826975124cSRafal Jaworowski 
5836975124cSRafal Jaworowski 	return (width);
5846975124cSRafal Jaworowski }
5856975124cSRafal Jaworowski 
5866975124cSRafal Jaworowski static void
5876975124cSRafal Jaworowski pcib_mbus_init_bridge(struct pcib_mbus_softc *sc, int bus, int slot, int func)
5886975124cSRafal Jaworowski {
5896975124cSRafal Jaworowski 	bus_addr_t io_base, mem_base;
5906975124cSRafal Jaworowski 	uint32_t io_limit, mem_limit;
5916975124cSRafal Jaworowski 	int secbus;
5926975124cSRafal Jaworowski 
5936975124cSRafal Jaworowski 	io_base = sc->sc_info->op_io_base;
5946975124cSRafal Jaworowski 	io_limit = io_base + sc->sc_info->op_io_size - 1;
5956975124cSRafal Jaworowski 	mem_base = sc->sc_info->op_mem_base;
5966975124cSRafal Jaworowski 	mem_limit = mem_base + sc->sc_info->op_mem_size - 1;
5976975124cSRafal Jaworowski 
5986975124cSRafal Jaworowski 	/* Configure I/O decode registers */
5996975124cSRafal Jaworowski 	pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITL_1,
6006975124cSRafal Jaworowski 	    io_limit >> 8, 1);
6016975124cSRafal Jaworowski 	pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITH_1,
6026975124cSRafal Jaworowski 	    io_limit >> 16, 2);
6036975124cSRafal Jaworowski 
6046975124cSRafal Jaworowski 	/* Configure memory decode registers */
6056975124cSRafal Jaworowski 	pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMBASE_1,
6066975124cSRafal Jaworowski 	    mem_base >> 16, 2);
6076975124cSRafal Jaworowski 	pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMLIMIT_1,
6086975124cSRafal Jaworowski 	    mem_limit >> 16, 2);
6096975124cSRafal Jaworowski 
6106975124cSRafal Jaworowski 	/* Disable memory prefetch decode */
6116975124cSRafal Jaworowski 	pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEL_1,
6126975124cSRafal Jaworowski 	    0x10, 2);
6136975124cSRafal Jaworowski 	pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEH_1,
6146975124cSRafal Jaworowski 	    0x0, 4);
6156975124cSRafal Jaworowski 	pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITL_1,
6166975124cSRafal Jaworowski 	    0xF, 2);
6176975124cSRafal Jaworowski 	pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITH_1,
6186975124cSRafal Jaworowski 	    0x0, 4);
6196975124cSRafal Jaworowski 
6206975124cSRafal Jaworowski 	secbus = pcib_mbus_read_config(sc->sc_dev, bus, slot, func,
6216975124cSRafal Jaworowski 	    PCIR_SECBUS_1, 1);
6226975124cSRafal Jaworowski 
6236975124cSRafal Jaworowski 	/* Configure buses behind the bridge */
6246975124cSRafal Jaworowski 	pcib_mbus_init(sc, secbus, PCI_SLOTMAX);
6256975124cSRafal Jaworowski }
6266975124cSRafal Jaworowski 
6276975124cSRafal Jaworowski static int
6286975124cSRafal Jaworowski pcib_mbus_init_resources(struct pcib_mbus_softc *sc, int bus, int slot,
6296975124cSRafal Jaworowski     int func, int hdrtype)
6306975124cSRafal Jaworowski {
6316975124cSRafal Jaworowski 	int maxbar = (hdrtype & PCIM_HDRTYPE) ? 0 : 6;
6326975124cSRafal Jaworowski 	int bar = 0, irq, pin, i;
6336975124cSRafal Jaworowski 
6346975124cSRafal Jaworowski 	/* Program the base address registers */
6356975124cSRafal Jaworowski 	while (bar < maxbar) {
6366975124cSRafal Jaworowski 		i = pcib_mbus_init_bar(sc, bus, slot, func, bar);
6376975124cSRafal Jaworowski 		bar += i;
6386975124cSRafal Jaworowski 		if (i < 0) {
6396975124cSRafal Jaworowski 			device_printf(sc->sc_dev,
6406975124cSRafal Jaworowski 			    "PCI IO/Memory space exhausted\n");
6416975124cSRafal Jaworowski 			return (ENOMEM);
6426975124cSRafal Jaworowski 		}
6436975124cSRafal Jaworowski 	}
6446975124cSRafal Jaworowski 
6456975124cSRafal Jaworowski 	/* Perform interrupt routing */
6466975124cSRafal Jaworowski 	pin = pcib_mbus_read_config(sc->sc_dev, bus, slot, func,
6476975124cSRafal Jaworowski 	    PCIR_INTPIN, 1);
6486975124cSRafal Jaworowski 
6496975124cSRafal Jaworowski 	if (sc->sc_info->op_get_irq != NULL)
6506975124cSRafal Jaworowski 		irq = sc->sc_info->op_get_irq(bus, slot, func, pin);
6516975124cSRafal Jaworowski 	else
6526975124cSRafal Jaworowski 		irq = sc->sc_info->op_irq;
6536975124cSRafal Jaworowski 
6546975124cSRafal Jaworowski 	if (irq >= 0)
6556975124cSRafal Jaworowski 		pcib_mbus_write_config(sc->sc_dev, bus, slot, func,
6566975124cSRafal Jaworowski 		    PCIR_INTLINE, irq, 1);
6576975124cSRafal Jaworowski 	else {
6586975124cSRafal Jaworowski 		device_printf(sc->sc_dev, "Missing IRQ routing information "
6596975124cSRafal Jaworowski 		    "for PCI device %u:%u:%u\n", bus, slot, func);
6606975124cSRafal Jaworowski 		return (ENXIO);
6616975124cSRafal Jaworowski 	}
6626975124cSRafal Jaworowski 
6636975124cSRafal Jaworowski 	return (0);
6646975124cSRafal Jaworowski }
6656975124cSRafal Jaworowski 
6666975124cSRafal Jaworowski static int
6676975124cSRafal Jaworowski pcib_mbus_init(struct pcib_mbus_softc *sc, int bus, int maxslot)
6686975124cSRafal Jaworowski {
6696975124cSRafal Jaworowski 	int slot, func, maxfunc, error;
6706975124cSRafal Jaworowski 	uint8_t hdrtype, command, class, subclass;
6716975124cSRafal Jaworowski 
6726975124cSRafal Jaworowski 	for (slot = 0; slot <= maxslot; slot++) {
6736975124cSRafal Jaworowski 		maxfunc = 0;
6746975124cSRafal Jaworowski 		for (func = 0; func <= maxfunc; func++) {
6756975124cSRafal Jaworowski 			hdrtype = pcib_mbus_read_config(sc->sc_dev, bus, slot,
6766975124cSRafal Jaworowski 			    func, PCIR_HDRTYPE, 1);
6776975124cSRafal Jaworowski 
6786975124cSRafal Jaworowski 			if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
6796975124cSRafal Jaworowski 				continue;
6806975124cSRafal Jaworowski 
6816975124cSRafal Jaworowski 			if (func == 0 && (hdrtype & PCIM_MFDEV))
6826975124cSRafal Jaworowski 				maxfunc = PCI_FUNCMAX;
6836975124cSRafal Jaworowski 
6846975124cSRafal Jaworowski 			command = pcib_mbus_read_config(sc->sc_dev, bus, slot,
6856975124cSRafal Jaworowski 			    func, PCIR_COMMAND, 1);
6866975124cSRafal Jaworowski 			command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
6876975124cSRafal Jaworowski 			pcib_mbus_write_config(sc->sc_dev, bus, slot, func,
6886975124cSRafal Jaworowski 			    PCIR_COMMAND, command, 1);
6896975124cSRafal Jaworowski 
6906975124cSRafal Jaworowski 			error = pcib_mbus_init_resources(sc, bus, slot, func,
6916975124cSRafal Jaworowski 			    hdrtype);
6926975124cSRafal Jaworowski 
6936975124cSRafal Jaworowski 			if (error)
6946975124cSRafal Jaworowski 				return (error);
6956975124cSRafal Jaworowski 
6966975124cSRafal Jaworowski 			command |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
6976975124cSRafal Jaworowski 			    PCIM_CMD_PORTEN;
6986975124cSRafal Jaworowski 			pcib_mbus_write_config(sc->sc_dev, bus, slot, func,
6996975124cSRafal Jaworowski 			    PCIR_COMMAND, command, 1);
7006975124cSRafal Jaworowski 
7016975124cSRafal Jaworowski 			/* Handle PCI-PCI bridges */
7026975124cSRafal Jaworowski 			class = pcib_mbus_read_config(sc->sc_dev, bus, slot,
7036975124cSRafal Jaworowski 			    func, PCIR_CLASS, 1);
7046975124cSRafal Jaworowski 			subclass = pcib_mbus_read_config(sc->sc_dev, bus, slot,
7056975124cSRafal Jaworowski 			    func, PCIR_SUBCLASS, 1);
7066975124cSRafal Jaworowski 
7076975124cSRafal Jaworowski 			if (class != PCIC_BRIDGE ||
7086975124cSRafal Jaworowski 			    subclass != PCIS_BRIDGE_PCI)
7096975124cSRafal Jaworowski 				continue;
7106975124cSRafal Jaworowski 
7116975124cSRafal Jaworowski 			pcib_mbus_init_bridge(sc, bus, slot, func);
7126975124cSRafal Jaworowski 		}
7136975124cSRafal Jaworowski 	}
7146975124cSRafal Jaworowski 
7156975124cSRafal Jaworowski 	/* Enable all ABCD interrupts */
7166975124cSRafal Jaworowski 	pcib_write_irq_mask(sc, (0xF << 24));
7176975124cSRafal Jaworowski 
7186975124cSRafal Jaworowski 	return (0);
7196975124cSRafal Jaworowski }
7206975124cSRafal Jaworowski 
7216975124cSRafal Jaworowski static struct resource *
7226975124cSRafal Jaworowski pcib_mbus_alloc_resource(device_t dev, device_t child, int type, int *rid,
7236975124cSRafal Jaworowski     u_long start, u_long end, u_long count, u_int flags)
7246975124cSRafal Jaworowski {
7256975124cSRafal Jaworowski 
7266975124cSRafal Jaworowski 	return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
7276975124cSRafal Jaworowski 	    type, rid, start, end, count, flags));
7286975124cSRafal Jaworowski }
7296975124cSRafal Jaworowski 
7306975124cSRafal Jaworowski static int
7316975124cSRafal Jaworowski pcib_mbus_release_resource(device_t dev, device_t child, int type, int rid,
7326975124cSRafal Jaworowski     struct resource *res)
7336975124cSRafal Jaworowski {
7346975124cSRafal Jaworowski 
7356975124cSRafal Jaworowski 	return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
7366975124cSRafal Jaworowski 	    type, rid, res));
7376975124cSRafal Jaworowski }
7386975124cSRafal Jaworowski 
7396975124cSRafal Jaworowski static int
7406975124cSRafal Jaworowski pcib_mbus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
7416975124cSRafal Jaworowski {
7426975124cSRafal Jaworowski 	struct pcib_mbus_softc *sc = device_get_softc(dev);
7436975124cSRafal Jaworowski 
7446975124cSRafal Jaworowski 	switch (which) {
7456975124cSRafal Jaworowski 	case PCIB_IVAR_BUS:
7466975124cSRafal Jaworowski 		*result = sc->sc_busnr;
7476975124cSRafal Jaworowski 		return (0);
7486975124cSRafal Jaworowski 	case PCIB_IVAR_DOMAIN:
7496975124cSRafal Jaworowski 		*result = device_get_unit(dev);
7506975124cSRafal Jaworowski 		return (0);
7516975124cSRafal Jaworowski 	}
7526975124cSRafal Jaworowski 
7536975124cSRafal Jaworowski 	return (ENOENT);
7546975124cSRafal Jaworowski }
7556975124cSRafal Jaworowski 
7566975124cSRafal Jaworowski static int
7576975124cSRafal Jaworowski pcib_mbus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
7586975124cSRafal Jaworowski {
7596975124cSRafal Jaworowski 	struct pcib_mbus_softc *sc = device_get_softc(dev);
7606975124cSRafal Jaworowski 
7616975124cSRafal Jaworowski 	switch (which) {
7626975124cSRafal Jaworowski 	case PCIB_IVAR_BUS:
7636975124cSRafal Jaworowski 		sc->sc_busnr = value;
7646975124cSRafal Jaworowski 		return (0);
7656975124cSRafal Jaworowski 	}
7666975124cSRafal Jaworowski 
7676975124cSRafal Jaworowski 	return (ENOENT);
7686975124cSRafal Jaworowski }
769