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