16975124cSRafal Jaworowski /*- 2db5ef4fcSRafal Jaworowski * Copyright (c) 2008 MARVELL INTERNATIONAL LTD. 3db5ef4fcSRafal Jaworowski * Copyright (c) 2010 The FreeBSD Foundation 46975124cSRafal Jaworowski * All rights reserved. 56975124cSRafal Jaworowski * 66975124cSRafal Jaworowski * Developed by Semihalf. 76975124cSRafal Jaworowski * 8db5ef4fcSRafal Jaworowski * Portions of this software were developed by Semihalf 9db5ef4fcSRafal Jaworowski * under sponsorship from the FreeBSD Foundation. 10db5ef4fcSRafal Jaworowski * 116975124cSRafal Jaworowski * Redistribution and use in source and binary forms, with or without 126975124cSRafal Jaworowski * modification, are permitted provided that the following conditions 136975124cSRafal Jaworowski * are met: 146975124cSRafal Jaworowski * 1. Redistributions of source code must retain the above copyright 156975124cSRafal Jaworowski * notice, this list of conditions and the following disclaimer. 166975124cSRafal Jaworowski * 2. Redistributions in binary form must reproduce the above copyright 176975124cSRafal Jaworowski * notice, this list of conditions and the following disclaimer in the 186975124cSRafal Jaworowski * documentation and/or other materials provided with the distribution. 196975124cSRafal Jaworowski * 3. Neither the name of MARVELL nor the names of contributors 206975124cSRafal Jaworowski * may be used to endorse or promote products derived from this software 216975124cSRafal Jaworowski * without specific prior written permission. 226975124cSRafal Jaworowski * 236975124cSRafal Jaworowski * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 246975124cSRafal Jaworowski * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 256975124cSRafal Jaworowski * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 266975124cSRafal Jaworowski * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 276975124cSRafal Jaworowski * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 286975124cSRafal Jaworowski * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 296975124cSRafal Jaworowski * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 306975124cSRafal Jaworowski * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 316975124cSRafal Jaworowski * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 326975124cSRafal Jaworowski * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 336975124cSRafal Jaworowski * SUCH DAMAGE. 346975124cSRafal Jaworowski */ 356975124cSRafal Jaworowski 366975124cSRafal Jaworowski /* 376975124cSRafal Jaworowski * Marvell integrated PCI/PCI-Express controller driver. 386975124cSRafal Jaworowski */ 396975124cSRafal Jaworowski 406975124cSRafal Jaworowski #include <sys/cdefs.h> 416975124cSRafal Jaworowski __FBSDID("$FreeBSD$"); 426975124cSRafal Jaworowski 436975124cSRafal Jaworowski #include <sys/param.h> 446975124cSRafal Jaworowski #include <sys/systm.h> 456975124cSRafal Jaworowski #include <sys/kernel.h> 466975124cSRafal Jaworowski #include <sys/lock.h> 476975124cSRafal Jaworowski #include <sys/malloc.h> 486975124cSRafal Jaworowski #include <sys/module.h> 496975124cSRafal Jaworowski #include <sys/mutex.h> 506975124cSRafal Jaworowski #include <sys/queue.h> 516975124cSRafal Jaworowski #include <sys/bus.h> 526975124cSRafal Jaworowski #include <sys/rman.h> 536975124cSRafal Jaworowski #include <sys/endian.h> 546975124cSRafal Jaworowski 556975124cSRafal Jaworowski #include <vm/vm.h> 566975124cSRafal Jaworowski #include <vm/pmap.h> 576975124cSRafal Jaworowski 58db5ef4fcSRafal Jaworowski #include <dev/fdt/fdt_common.h> 59db5ef4fcSRafal Jaworowski #include <dev/ofw/ofw_bus.h> 60db5ef4fcSRafal Jaworowski #include <dev/ofw/ofw_bus_subr.h> 616975124cSRafal Jaworowski #include <dev/pci/pcivar.h> 626975124cSRafal Jaworowski #include <dev/pci/pcireg.h> 636975124cSRafal Jaworowski #include <dev/pci/pcib_private.h> 646975124cSRafal Jaworowski 65db5ef4fcSRafal Jaworowski #include "ofw_bus_if.h" 666975124cSRafal Jaworowski #include "pcib_if.h" 676975124cSRafal Jaworowski 686975124cSRafal Jaworowski #include <machine/resource.h> 696975124cSRafal Jaworowski #include <machine/bus.h> 706975124cSRafal Jaworowski 716975124cSRafal Jaworowski #include <arm/mv/mvreg.h> 726975124cSRafal Jaworowski #include <arm/mv/mvvar.h> 73db5ef4fcSRafal Jaworowski #include <arm/mv/mvwin.h> 746975124cSRafal Jaworowski 756975124cSRafal Jaworowski #define PCI_CFG_ENA (1 << 31) 766975124cSRafal Jaworowski #define PCI_CFG_BUS(bus) (((bus) & 0xff) << 16) 776975124cSRafal Jaworowski #define PCI_CFG_DEV(dev) (((dev) & 0x1f) << 11) 786975124cSRafal Jaworowski #define PCI_CFG_FUN(fun) (((fun) & 0x7) << 8) 796975124cSRafal Jaworowski #define PCI_CFG_PCIE_REG(reg) ((reg) & 0xfc) 806975124cSRafal Jaworowski 816975124cSRafal Jaworowski #define PCI_REG_CFG_ADDR 0x0C78 826975124cSRafal Jaworowski #define PCI_REG_CFG_DATA 0x0C7C 836975124cSRafal Jaworowski #define PCI_REG_P2P_CONF 0x1D14 846975124cSRafal Jaworowski 856975124cSRafal Jaworowski #define PCIE_REG_CFG_ADDR 0x18F8 866975124cSRafal Jaworowski #define PCIE_REG_CFG_DATA 0x18FC 876975124cSRafal Jaworowski #define PCIE_REG_CONTROL 0x1A00 886975124cSRafal Jaworowski #define PCIE_CTRL_LINK1X 0x00000001 896975124cSRafal Jaworowski #define PCIE_REG_STATUS 0x1A04 906975124cSRafal Jaworowski #define PCIE_REG_IRQ_MASK 0x1910 916975124cSRafal Jaworowski 924e883c81SRafal Jaworowski #define STATUS_LINK_DOWN 1 936975124cSRafal Jaworowski #define STATUS_BUS_OFFS 8 946975124cSRafal Jaworowski #define STATUS_BUS_MASK (0xFF << STATUS_BUS_OFFS) 956975124cSRafal Jaworowski #define STATUS_DEV_OFFS 16 966975124cSRafal Jaworowski #define STATUS_DEV_MASK (0x1F << STATUS_DEV_OFFS) 976975124cSRafal Jaworowski 986975124cSRafal Jaworowski #define P2P_CONF_BUS_OFFS 16 996975124cSRafal Jaworowski #define P2P_CONF_BUS_MASK (0xFF << P2P_CONF_BUS_OFFS) 1006975124cSRafal Jaworowski #define P2P_CONF_DEV_OFFS 24 1016975124cSRafal Jaworowski #define P2P_CONF_DEV_MASK (0x1F << P2P_CONF_DEV_OFFS) 1026975124cSRafal Jaworowski 1036975124cSRafal Jaworowski #define PCI_VENDORID_MRVL 0x11AB 1046975124cSRafal Jaworowski 105db5ef4fcSRafal Jaworowski struct mv_pcib_softc { 1066975124cSRafal Jaworowski device_t sc_dev; 1076975124cSRafal Jaworowski 108db5ef4fcSRafal Jaworowski struct rman sc_mem_rman; 109db5ef4fcSRafal Jaworowski bus_addr_t sc_mem_base; 110db5ef4fcSRafal Jaworowski bus_addr_t sc_mem_size; 111db5ef4fcSRafal Jaworowski bus_addr_t sc_mem_alloc; /* Next allocation. */ 112db5ef4fcSRafal Jaworowski int sc_mem_win_target; 113db5ef4fcSRafal Jaworowski int sc_mem_win_attr; 1146975124cSRafal Jaworowski 115db5ef4fcSRafal Jaworowski struct rman sc_io_rman; 116db5ef4fcSRafal Jaworowski bus_addr_t sc_io_base; 117db5ef4fcSRafal Jaworowski bus_addr_t sc_io_size; 118db5ef4fcSRafal Jaworowski bus_addr_t sc_io_alloc; /* Next allocation. */ 119db5ef4fcSRafal Jaworowski int sc_io_win_target; 120db5ef4fcSRafal Jaworowski int sc_io_win_attr; 1216975124cSRafal Jaworowski 1226975124cSRafal Jaworowski struct resource *sc_res; 1236975124cSRafal Jaworowski bus_space_handle_t sc_bsh; 1246975124cSRafal Jaworowski bus_space_tag_t sc_bst; 1256975124cSRafal Jaworowski int sc_rid; 1266975124cSRafal Jaworowski 1276975124cSRafal Jaworowski int sc_busnr; /* Host bridge bus number */ 1286975124cSRafal Jaworowski int sc_devnr; /* Host bridge device number */ 129db5ef4fcSRafal Jaworowski int sc_type; 1306975124cSRafal Jaworowski 131db5ef4fcSRafal Jaworowski struct fdt_pci_intr sc_intr_info; 1326975124cSRafal Jaworowski }; 1336975124cSRafal Jaworowski 134db5ef4fcSRafal Jaworowski /* Local forward prototypes */ 135db5ef4fcSRafal Jaworowski static int mv_pcib_decode_win(phandle_t, struct mv_pcib_softc *); 136db5ef4fcSRafal Jaworowski static void mv_pcib_hw_cfginit(void); 137db5ef4fcSRafal Jaworowski static uint32_t mv_pcib_hw_cfgread(struct mv_pcib_softc *, u_int, u_int, 138db5ef4fcSRafal Jaworowski u_int, u_int, int); 139db5ef4fcSRafal Jaworowski static void mv_pcib_hw_cfgwrite(struct mv_pcib_softc *, u_int, u_int, 140db5ef4fcSRafal Jaworowski u_int, u_int, uint32_t, int); 141db5ef4fcSRafal Jaworowski static int mv_pcib_init(struct mv_pcib_softc *, int, int); 142db5ef4fcSRafal Jaworowski static int mv_pcib_init_all_bars(struct mv_pcib_softc *, int, int, int, int); 143db5ef4fcSRafal Jaworowski static void mv_pcib_init_bridge(struct mv_pcib_softc *, int, int, int); 144db5ef4fcSRafal Jaworowski static int mv_pcib_intr_info(phandle_t, struct mv_pcib_softc *); 145db5ef4fcSRafal Jaworowski static inline void pcib_write_irq_mask(struct mv_pcib_softc *, uint32_t); 1466975124cSRafal Jaworowski 147db5ef4fcSRafal Jaworowski 148db5ef4fcSRafal Jaworowski /* Forward prototypes */ 149db5ef4fcSRafal Jaworowski static int mv_pcib_probe(device_t); 150db5ef4fcSRafal Jaworowski static int mv_pcib_attach(device_t); 151db5ef4fcSRafal Jaworowski 152db5ef4fcSRafal Jaworowski static struct resource *mv_pcib_alloc_resource(device_t, device_t, int, int *, 1536975124cSRafal Jaworowski u_long, u_long, u_long, u_int); 154db5ef4fcSRafal Jaworowski static int mv_pcib_release_resource(device_t, device_t, int, int, 1556975124cSRafal Jaworowski struct resource *); 156db5ef4fcSRafal Jaworowski static int mv_pcib_read_ivar(device_t, device_t, int, uintptr_t *); 157db5ef4fcSRafal Jaworowski static int mv_pcib_write_ivar(device_t, device_t, int, uintptr_t); 1586975124cSRafal Jaworowski 159db5ef4fcSRafal Jaworowski static int mv_pcib_maxslots(device_t); 160db5ef4fcSRafal Jaworowski static uint32_t mv_pcib_read_config(device_t, u_int, u_int, u_int, u_int, int); 161db5ef4fcSRafal Jaworowski static void mv_pcib_write_config(device_t, u_int, u_int, u_int, u_int, 1626975124cSRafal Jaworowski uint32_t, int); 163db5ef4fcSRafal Jaworowski static int mv_pcib_route_interrupt(device_t, device_t, int); 1646975124cSRafal Jaworowski 1656975124cSRafal Jaworowski /* 1666975124cSRafal Jaworowski * Bus interface definitions. 1676975124cSRafal Jaworowski */ 168db5ef4fcSRafal Jaworowski static device_method_t mv_pcib_methods[] = { 1696975124cSRafal Jaworowski /* Device interface */ 170db5ef4fcSRafal Jaworowski DEVMETHOD(device_probe, mv_pcib_probe), 171db5ef4fcSRafal Jaworowski DEVMETHOD(device_attach, mv_pcib_attach), 1726975124cSRafal Jaworowski 1736975124cSRafal Jaworowski /* Bus interface */ 1746975124cSRafal Jaworowski DEVMETHOD(bus_print_child, bus_generic_print_child), 175db5ef4fcSRafal Jaworowski DEVMETHOD(bus_read_ivar, mv_pcib_read_ivar), 176db5ef4fcSRafal Jaworowski DEVMETHOD(bus_write_ivar, mv_pcib_write_ivar), 177db5ef4fcSRafal Jaworowski DEVMETHOD(bus_alloc_resource, mv_pcib_alloc_resource), 178db5ef4fcSRafal Jaworowski DEVMETHOD(bus_release_resource, mv_pcib_release_resource), 1796975124cSRafal Jaworowski DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 1806975124cSRafal Jaworowski DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 1816975124cSRafal Jaworowski DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 1826975124cSRafal Jaworowski DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 1836975124cSRafal Jaworowski 1846975124cSRafal Jaworowski /* pcib interface */ 185db5ef4fcSRafal Jaworowski DEVMETHOD(pcib_maxslots, mv_pcib_maxslots), 186db5ef4fcSRafal Jaworowski DEVMETHOD(pcib_read_config, mv_pcib_read_config), 187db5ef4fcSRafal Jaworowski DEVMETHOD(pcib_write_config, mv_pcib_write_config), 188db5ef4fcSRafal Jaworowski DEVMETHOD(pcib_route_interrupt, mv_pcib_route_interrupt), 189db5ef4fcSRafal Jaworowski 190db5ef4fcSRafal Jaworowski /* OFW bus interface */ 191db5ef4fcSRafal Jaworowski DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 192db5ef4fcSRafal Jaworowski DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 193db5ef4fcSRafal Jaworowski DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 194db5ef4fcSRafal Jaworowski DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 195db5ef4fcSRafal Jaworowski DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 1966975124cSRafal Jaworowski 1976975124cSRafal Jaworowski { 0, 0 } 1986975124cSRafal Jaworowski }; 1996975124cSRafal Jaworowski 200db5ef4fcSRafal Jaworowski static driver_t mv_pcib_driver = { 2016975124cSRafal Jaworowski "pcib", 202db5ef4fcSRafal Jaworowski mv_pcib_methods, 203db5ef4fcSRafal Jaworowski sizeof(struct mv_pcib_softc), 2046975124cSRafal Jaworowski }; 2056975124cSRafal Jaworowski 2066975124cSRafal Jaworowski devclass_t pcib_devclass; 2076975124cSRafal Jaworowski 208db5ef4fcSRafal Jaworowski DRIVER_MODULE(pcib, fdtbus, mv_pcib_driver, pcib_devclass, 0, 0); 2096975124cSRafal Jaworowski 2106975124cSRafal Jaworowski static struct mtx pcicfg_mtx; 2116975124cSRafal Jaworowski 212db5ef4fcSRafal Jaworowski static int 213db5ef4fcSRafal Jaworowski mv_pcib_probe(device_t self) 2146975124cSRafal Jaworowski { 215*1b96faf8SMarcel Moolenaar phandle_t node; 2166975124cSRafal Jaworowski 217*1b96faf8SMarcel Moolenaar node = ofw_bus_get_node(self); 218*1b96faf8SMarcel Moolenaar if (!fdt_is_type(node, "pci")) 219db5ef4fcSRafal Jaworowski return (ENXIO); 220*1b96faf8SMarcel Moolenaar 221*1b96faf8SMarcel Moolenaar if (!(fdt_is_compatible(node, "mrvl,pcie") || 222*1b96faf8SMarcel Moolenaar fdt_is_compatible(node, "mrvl,pci"))) 223db5ef4fcSRafal Jaworowski return (ENXIO); 2246975124cSRafal Jaworowski 225db5ef4fcSRafal Jaworowski device_set_desc(self, "Marvell Integrated PCI/PCI-E Controller"); 226db5ef4fcSRafal Jaworowski return (BUS_PROBE_DEFAULT); 227db5ef4fcSRafal Jaworowski } 228db5ef4fcSRafal Jaworowski 229db5ef4fcSRafal Jaworowski static int 230db5ef4fcSRafal Jaworowski mv_pcib_attach(device_t self) 231db5ef4fcSRafal Jaworowski { 232db5ef4fcSRafal Jaworowski struct mv_pcib_softc *sc; 233db5ef4fcSRafal Jaworowski phandle_t node, parnode; 234db5ef4fcSRafal Jaworowski uint32_t val; 235db5ef4fcSRafal Jaworowski int err; 236db5ef4fcSRafal Jaworowski 237db5ef4fcSRafal Jaworowski sc = device_get_softc(self); 238db5ef4fcSRafal Jaworowski sc->sc_dev = self; 239db5ef4fcSRafal Jaworowski 240*1b96faf8SMarcel Moolenaar node = ofw_bus_get_node(self); 241*1b96faf8SMarcel Moolenaar parnode = OF_parent(node); 242*1b96faf8SMarcel Moolenaar if (fdt_is_compatible(node, "mrvl,pcie")) { 243db5ef4fcSRafal Jaworowski sc->sc_type = MV_TYPE_PCIE; 244db5ef4fcSRafal Jaworowski sc->sc_mem_win_target = MV_WIN_PCIE_MEM_TARGET; 245db5ef4fcSRafal Jaworowski sc->sc_mem_win_attr = MV_WIN_PCIE_MEM_ATTR; 246db5ef4fcSRafal Jaworowski sc->sc_io_win_target = MV_WIN_PCIE_IO_TARGET; 247db5ef4fcSRafal Jaworowski sc->sc_io_win_attr = MV_WIN_PCIE_IO_ATTR; 248db5ef4fcSRafal Jaworowski #ifdef SOC_MV_ORION 249*1b96faf8SMarcel Moolenaar } else if (fdt_is_compatible(node, "mrvl,pci")) { 250db5ef4fcSRafal Jaworowski sc->sc_type = MV_TYPE_PCI; 251db5ef4fcSRafal Jaworowski sc->sc_mem_win_target = MV_WIN_PCI_MEM_TARGET; 252db5ef4fcSRafal Jaworowski sc->sc_mem_win_attr = MV_WIN_PCI_MEM_ATTR; 253db5ef4fcSRafal Jaworowski sc->sc_io_win_target = MV_WIN_PCI_IO_TARGET; 254db5ef4fcSRafal Jaworowski sc->sc_io_win_attr = MV_WIN_PCI_IO_ATTR; 255db5ef4fcSRafal Jaworowski #endif 256db5ef4fcSRafal Jaworowski } else 257db5ef4fcSRafal Jaworowski return (ENXIO); 258db5ef4fcSRafal Jaworowski 259db5ef4fcSRafal Jaworowski /* 260db5ef4fcSRafal Jaworowski * Get PCI interrupt info. 261db5ef4fcSRafal Jaworowski */ 262db5ef4fcSRafal Jaworowski if (mv_pcib_intr_info(node, sc) != 0) { 263db5ef4fcSRafal Jaworowski device_printf(self, "could not retrieve interrupt info\n"); 264db5ef4fcSRafal Jaworowski return (ENXIO); 265db5ef4fcSRafal Jaworowski } 266db5ef4fcSRafal Jaworowski 267db5ef4fcSRafal Jaworowski /* 268db5ef4fcSRafal Jaworowski * Retrieve our mem-mapped registers range. 269db5ef4fcSRafal Jaworowski */ 270db5ef4fcSRafal Jaworowski sc->sc_rid = 0; 271db5ef4fcSRafal Jaworowski sc->sc_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &sc->sc_rid, 272db5ef4fcSRafal Jaworowski RF_ACTIVE); 273db5ef4fcSRafal Jaworowski if (sc->sc_res == NULL) { 274db5ef4fcSRafal Jaworowski device_printf(self, "could not map memory\n"); 275db5ef4fcSRafal Jaworowski return (ENXIO); 276db5ef4fcSRafal Jaworowski } 277db5ef4fcSRafal Jaworowski sc->sc_bst = rman_get_bustag(sc->sc_res); 278db5ef4fcSRafal Jaworowski sc->sc_bsh = rman_get_bushandle(sc->sc_res); 279db5ef4fcSRafal Jaworowski 280db5ef4fcSRafal Jaworowski /* 281db5ef4fcSRafal Jaworowski * Configure decode windows for PCI(E) access. 282db5ef4fcSRafal Jaworowski */ 283db5ef4fcSRafal Jaworowski if (mv_pcib_decode_win(node, sc) != 0) 284db5ef4fcSRafal Jaworowski return (ENXIO); 285db5ef4fcSRafal Jaworowski 286db5ef4fcSRafal Jaworowski mv_pcib_hw_cfginit(); 287db5ef4fcSRafal Jaworowski 288db5ef4fcSRafal Jaworowski /* 289db5ef4fcSRafal Jaworowski * Enable PCI bridge. 290db5ef4fcSRafal Jaworowski */ 291db5ef4fcSRafal Jaworowski val = mv_pcib_hw_cfgread(sc, sc->sc_busnr, sc->sc_devnr, 0, 292db5ef4fcSRafal Jaworowski PCIR_COMMAND, 2); 293db5ef4fcSRafal Jaworowski val |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | 294db5ef4fcSRafal Jaworowski PCIM_CMD_PORTEN; 295db5ef4fcSRafal Jaworowski mv_pcib_hw_cfgwrite(sc, sc->sc_busnr, sc->sc_devnr, 0, 296db5ef4fcSRafal Jaworowski PCIR_COMMAND, val, 2); 297db5ef4fcSRafal Jaworowski 298db5ef4fcSRafal Jaworowski sc->sc_mem_alloc = sc->sc_mem_base; 299db5ef4fcSRafal Jaworowski sc->sc_io_alloc = sc->sc_io_base; 300db5ef4fcSRafal Jaworowski 301db5ef4fcSRafal Jaworowski sc->sc_mem_rman.rm_type = RMAN_ARRAY; 302db5ef4fcSRafal Jaworowski err = rman_init(&sc->sc_mem_rman); 303db5ef4fcSRafal Jaworowski if (err) 304db5ef4fcSRafal Jaworowski return (err); 305db5ef4fcSRafal Jaworowski 306db5ef4fcSRafal Jaworowski sc->sc_io_rman.rm_type = RMAN_ARRAY; 307db5ef4fcSRafal Jaworowski err = rman_init(&sc->sc_io_rman); 308db5ef4fcSRafal Jaworowski if (err) { 309db5ef4fcSRafal Jaworowski rman_fini(&sc->sc_mem_rman); 310db5ef4fcSRafal Jaworowski return (err); 311db5ef4fcSRafal Jaworowski } 312db5ef4fcSRafal Jaworowski 313db5ef4fcSRafal Jaworowski err = rman_manage_region(&sc->sc_mem_rman, sc->sc_mem_base, 314db5ef4fcSRafal Jaworowski sc->sc_mem_base + sc->sc_mem_size - 1); 315db5ef4fcSRafal Jaworowski if (err) 316db5ef4fcSRafal Jaworowski goto error; 317db5ef4fcSRafal Jaworowski 318db5ef4fcSRafal Jaworowski err = rman_manage_region(&sc->sc_io_rman, sc->sc_io_base, 319db5ef4fcSRafal Jaworowski sc->sc_io_base + sc->sc_io_size - 1); 320db5ef4fcSRafal Jaworowski if (err) 321db5ef4fcSRafal Jaworowski goto error; 322db5ef4fcSRafal Jaworowski 323db5ef4fcSRafal Jaworowski err = mv_pcib_init(sc, sc->sc_busnr, mv_pcib_maxslots(sc->sc_dev)); 324db5ef4fcSRafal Jaworowski if (err) 325db5ef4fcSRafal Jaworowski goto error; 326db5ef4fcSRafal Jaworowski 327db5ef4fcSRafal Jaworowski device_add_child(self, "pci", -1); 328db5ef4fcSRafal Jaworowski return (bus_generic_attach(self)); 329db5ef4fcSRafal Jaworowski 330db5ef4fcSRafal Jaworowski error: 331db5ef4fcSRafal Jaworowski /* XXX SYS_RES_ should be released here */ 332db5ef4fcSRafal Jaworowski rman_fini(&sc->sc_mem_rman); 333db5ef4fcSRafal Jaworowski rman_fini(&sc->sc_io_rman); 334db5ef4fcSRafal Jaworowski return (err); 335db5ef4fcSRafal Jaworowski } 336db5ef4fcSRafal Jaworowski 337db5ef4fcSRafal Jaworowski static int 338db5ef4fcSRafal Jaworowski mv_pcib_init_bar(struct mv_pcib_softc *sc, int bus, int slot, int func, 339db5ef4fcSRafal Jaworowski int barno) 340db5ef4fcSRafal Jaworowski { 341db5ef4fcSRafal Jaworowski bus_addr_t *allocp, limit; 342db5ef4fcSRafal Jaworowski uint32_t addr, bar, mask, size; 343db5ef4fcSRafal Jaworowski int reg, width; 344db5ef4fcSRafal Jaworowski 345db5ef4fcSRafal Jaworowski reg = PCIR_BAR(barno); 346db5ef4fcSRafal Jaworowski bar = mv_pcib_read_config(sc->sc_dev, bus, slot, func, reg, 4); 347db5ef4fcSRafal Jaworowski if (bar == 0) 348db5ef4fcSRafal Jaworowski return (1); 349db5ef4fcSRafal Jaworowski 350db5ef4fcSRafal Jaworowski /* Calculate BAR size: 64 or 32 bit (in 32-bit units) */ 351db5ef4fcSRafal Jaworowski width = ((bar & 7) == 4) ? 2 : 1; 352db5ef4fcSRafal Jaworowski 353db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4); 354db5ef4fcSRafal Jaworowski size = mv_pcib_read_config(sc->sc_dev, bus, slot, func, reg, 4); 355db5ef4fcSRafal Jaworowski 356db5ef4fcSRafal Jaworowski /* Get BAR type and size */ 357db5ef4fcSRafal Jaworowski if (bar & 1) { 358db5ef4fcSRafal Jaworowski /* I/O port */ 359db5ef4fcSRafal Jaworowski allocp = &sc->sc_io_alloc; 360db5ef4fcSRafal Jaworowski limit = sc->sc_io_base + sc->sc_io_size; 361db5ef4fcSRafal Jaworowski size &= ~0x3; 362db5ef4fcSRafal Jaworowski if ((size & 0xffff0000) == 0) 363db5ef4fcSRafal Jaworowski size |= 0xffff0000; 364db5ef4fcSRafal Jaworowski } else { 365db5ef4fcSRafal Jaworowski /* Memory */ 366db5ef4fcSRafal Jaworowski allocp = &sc->sc_mem_alloc; 367db5ef4fcSRafal Jaworowski limit = sc->sc_mem_base + sc->sc_mem_size; 368db5ef4fcSRafal Jaworowski size &= ~0xF; 369db5ef4fcSRafal Jaworowski } 370db5ef4fcSRafal Jaworowski mask = ~size; 371db5ef4fcSRafal Jaworowski size = mask + 1; 372db5ef4fcSRafal Jaworowski 373db5ef4fcSRafal Jaworowski /* Sanity check (must be a power of 2) */ 374db5ef4fcSRafal Jaworowski if (size & mask) 375db5ef4fcSRafal Jaworowski return (width); 376db5ef4fcSRafal Jaworowski 377db5ef4fcSRafal Jaworowski addr = (*allocp + mask) & ~mask; 378db5ef4fcSRafal Jaworowski if ((*allocp = addr + size) > limit) 379db5ef4fcSRafal Jaworowski return (-1); 380db5ef4fcSRafal Jaworowski 381db5ef4fcSRafal Jaworowski if (bootverbose) 382db5ef4fcSRafal Jaworowski printf("PCI %u:%u:%u: reg %x: size=%08x: addr=%08x\n", 383db5ef4fcSRafal Jaworowski bus, slot, func, reg, size, addr); 384db5ef4fcSRafal Jaworowski 385db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4); 386db5ef4fcSRafal Jaworowski if (width == 2) 387db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg + 4, 388db5ef4fcSRafal Jaworowski 0, 4); 389db5ef4fcSRafal Jaworowski 390db5ef4fcSRafal Jaworowski return (width); 3916975124cSRafal Jaworowski } 3926975124cSRafal Jaworowski 3936975124cSRafal Jaworowski static void 394db5ef4fcSRafal Jaworowski mv_pcib_init_bridge(struct mv_pcib_softc *sc, int bus, int slot, int func) 395db5ef4fcSRafal Jaworowski { 396db5ef4fcSRafal Jaworowski bus_addr_t io_base, mem_base; 397db5ef4fcSRafal Jaworowski uint32_t io_limit, mem_limit; 398db5ef4fcSRafal Jaworowski int secbus; 399db5ef4fcSRafal Jaworowski 400db5ef4fcSRafal Jaworowski io_base = sc->sc_io_base; 401db5ef4fcSRafal Jaworowski io_limit = io_base + sc->sc_io_size - 1; 402db5ef4fcSRafal Jaworowski mem_base = sc->sc_mem_base; 403db5ef4fcSRafal Jaworowski mem_limit = mem_base + sc->sc_mem_size - 1; 404db5ef4fcSRafal Jaworowski 405db5ef4fcSRafal Jaworowski /* Configure I/O decode registers */ 406db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOBASEL_1, 407db5ef4fcSRafal Jaworowski io_base >> 8, 1); 408db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOBASEH_1, 409db5ef4fcSRafal Jaworowski io_base >> 16, 2); 410db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITL_1, 411db5ef4fcSRafal Jaworowski io_limit >> 8, 1); 412db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITH_1, 413db5ef4fcSRafal Jaworowski io_limit >> 16, 2); 414db5ef4fcSRafal Jaworowski 415db5ef4fcSRafal Jaworowski /* Configure memory decode registers */ 416db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMBASE_1, 417db5ef4fcSRafal Jaworowski mem_base >> 16, 2); 418db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMLIMIT_1, 419db5ef4fcSRafal Jaworowski mem_limit >> 16, 2); 420db5ef4fcSRafal Jaworowski 421db5ef4fcSRafal Jaworowski /* Disable memory prefetch decode */ 422db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEL_1, 423db5ef4fcSRafal Jaworowski 0x10, 2); 424db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEH_1, 425db5ef4fcSRafal Jaworowski 0x0, 4); 426db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITL_1, 427db5ef4fcSRafal Jaworowski 0xF, 2); 428db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITH_1, 429db5ef4fcSRafal Jaworowski 0x0, 4); 430db5ef4fcSRafal Jaworowski 431db5ef4fcSRafal Jaworowski secbus = mv_pcib_read_config(sc->sc_dev, bus, slot, func, 432db5ef4fcSRafal Jaworowski PCIR_SECBUS_1, 1); 433db5ef4fcSRafal Jaworowski 434db5ef4fcSRafal Jaworowski /* Configure buses behind the bridge */ 435db5ef4fcSRafal Jaworowski mv_pcib_init(sc, secbus, PCI_SLOTMAX); 436db5ef4fcSRafal Jaworowski } 437db5ef4fcSRafal Jaworowski 438db5ef4fcSRafal Jaworowski static int 439db5ef4fcSRafal Jaworowski mv_pcib_init(struct mv_pcib_softc *sc, int bus, int maxslot) 440db5ef4fcSRafal Jaworowski { 441db5ef4fcSRafal Jaworowski int slot, func, maxfunc, error; 442db5ef4fcSRafal Jaworowski uint8_t hdrtype, command, class, subclass; 443db5ef4fcSRafal Jaworowski 444db5ef4fcSRafal Jaworowski for (slot = 0; slot <= maxslot; slot++) { 445db5ef4fcSRafal Jaworowski maxfunc = 0; 446db5ef4fcSRafal Jaworowski for (func = 0; func <= maxfunc; func++) { 447db5ef4fcSRafal Jaworowski hdrtype = mv_pcib_read_config(sc->sc_dev, bus, slot, 448db5ef4fcSRafal Jaworowski func, PCIR_HDRTYPE, 1); 449db5ef4fcSRafal Jaworowski 450db5ef4fcSRafal Jaworowski if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) 451db5ef4fcSRafal Jaworowski continue; 452db5ef4fcSRafal Jaworowski 453db5ef4fcSRafal Jaworowski if (func == 0 && (hdrtype & PCIM_MFDEV)) 454db5ef4fcSRafal Jaworowski maxfunc = PCI_FUNCMAX; 455db5ef4fcSRafal Jaworowski 456db5ef4fcSRafal Jaworowski command = mv_pcib_read_config(sc->sc_dev, bus, slot, 457db5ef4fcSRafal Jaworowski func, PCIR_COMMAND, 1); 458db5ef4fcSRafal Jaworowski command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN); 459db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, 460db5ef4fcSRafal Jaworowski PCIR_COMMAND, command, 1); 461db5ef4fcSRafal Jaworowski 462db5ef4fcSRafal Jaworowski error = mv_pcib_init_all_bars(sc, bus, slot, func, 463db5ef4fcSRafal Jaworowski hdrtype); 464db5ef4fcSRafal Jaworowski 465db5ef4fcSRafal Jaworowski if (error) 466db5ef4fcSRafal Jaworowski return (error); 467db5ef4fcSRafal Jaworowski 468db5ef4fcSRafal Jaworowski command |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | 469db5ef4fcSRafal Jaworowski PCIM_CMD_PORTEN; 470db5ef4fcSRafal Jaworowski mv_pcib_write_config(sc->sc_dev, bus, slot, func, 471db5ef4fcSRafal Jaworowski PCIR_COMMAND, command, 1); 472db5ef4fcSRafal Jaworowski 473db5ef4fcSRafal Jaworowski /* Handle PCI-PCI bridges */ 474db5ef4fcSRafal Jaworowski class = mv_pcib_read_config(sc->sc_dev, bus, slot, 475db5ef4fcSRafal Jaworowski func, PCIR_CLASS, 1); 476db5ef4fcSRafal Jaworowski subclass = mv_pcib_read_config(sc->sc_dev, bus, slot, 477db5ef4fcSRafal Jaworowski func, PCIR_SUBCLASS, 1); 478db5ef4fcSRafal Jaworowski 479db5ef4fcSRafal Jaworowski if (class != PCIC_BRIDGE || 480db5ef4fcSRafal Jaworowski subclass != PCIS_BRIDGE_PCI) 481db5ef4fcSRafal Jaworowski continue; 482db5ef4fcSRafal Jaworowski 483db5ef4fcSRafal Jaworowski mv_pcib_init_bridge(sc, bus, slot, func); 484db5ef4fcSRafal Jaworowski } 485db5ef4fcSRafal Jaworowski } 486db5ef4fcSRafal Jaworowski 487db5ef4fcSRafal Jaworowski /* Enable all ABCD interrupts */ 488db5ef4fcSRafal Jaworowski pcib_write_irq_mask(sc, (0xF << 24)); 489db5ef4fcSRafal Jaworowski 490db5ef4fcSRafal Jaworowski return (0); 491db5ef4fcSRafal Jaworowski } 492db5ef4fcSRafal Jaworowski 493db5ef4fcSRafal Jaworowski static int 494db5ef4fcSRafal Jaworowski mv_pcib_init_all_bars(struct mv_pcib_softc *sc, int bus, int slot, 495db5ef4fcSRafal Jaworowski int func, int hdrtype) 496db5ef4fcSRafal Jaworowski { 497db5ef4fcSRafal Jaworowski int maxbar, bar, i; 498db5ef4fcSRafal Jaworowski 499db5ef4fcSRafal Jaworowski maxbar = (hdrtype & PCIM_HDRTYPE) ? 0 : 6; 500db5ef4fcSRafal Jaworowski bar = 0; 501db5ef4fcSRafal Jaworowski 502db5ef4fcSRafal Jaworowski /* Program the base address registers */ 503db5ef4fcSRafal Jaworowski while (bar < maxbar) { 504db5ef4fcSRafal Jaworowski i = mv_pcib_init_bar(sc, bus, slot, func, bar); 505db5ef4fcSRafal Jaworowski bar += i; 506db5ef4fcSRafal Jaworowski if (i < 0) { 507db5ef4fcSRafal Jaworowski device_printf(sc->sc_dev, 508db5ef4fcSRafal Jaworowski "PCI IO/Memory space exhausted\n"); 509db5ef4fcSRafal Jaworowski return (ENOMEM); 510db5ef4fcSRafal Jaworowski } 511db5ef4fcSRafal Jaworowski } 512db5ef4fcSRafal Jaworowski 513db5ef4fcSRafal Jaworowski return (0); 514db5ef4fcSRafal Jaworowski } 515db5ef4fcSRafal Jaworowski 516db5ef4fcSRafal Jaworowski static struct resource * 517db5ef4fcSRafal Jaworowski mv_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, 518db5ef4fcSRafal Jaworowski u_long start, u_long end, u_long count, u_int flags) 519db5ef4fcSRafal Jaworowski { 520db5ef4fcSRafal Jaworowski struct mv_pcib_softc *sc = device_get_softc(dev); 521db5ef4fcSRafal Jaworowski struct rman *rm = NULL; 522db5ef4fcSRafal Jaworowski struct resource *res; 523db5ef4fcSRafal Jaworowski 524db5ef4fcSRafal Jaworowski switch (type) { 525db5ef4fcSRafal Jaworowski case SYS_RES_IOPORT: 526db5ef4fcSRafal Jaworowski rm = &sc->sc_io_rman; 527db5ef4fcSRafal Jaworowski break; 528db5ef4fcSRafal Jaworowski case SYS_RES_MEMORY: 529db5ef4fcSRafal Jaworowski rm = &sc->sc_mem_rman; 530db5ef4fcSRafal Jaworowski break; 531db5ef4fcSRafal Jaworowski default: 532db5ef4fcSRafal Jaworowski return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, 533db5ef4fcSRafal Jaworowski type, rid, start, end, count, flags)); 534db5ef4fcSRafal Jaworowski }; 535db5ef4fcSRafal Jaworowski 536db5ef4fcSRafal Jaworowski res = rman_reserve_resource(rm, start, end, count, flags, child); 537db5ef4fcSRafal Jaworowski if (res == NULL) 538db5ef4fcSRafal Jaworowski return (NULL); 539db5ef4fcSRafal Jaworowski 540db5ef4fcSRafal Jaworowski rman_set_rid(res, *rid); 541db5ef4fcSRafal Jaworowski rman_set_bustag(res, fdtbus_bs_tag); 542db5ef4fcSRafal Jaworowski rman_set_bushandle(res, start); 543db5ef4fcSRafal Jaworowski 544db5ef4fcSRafal Jaworowski if (flags & RF_ACTIVE) 545db5ef4fcSRafal Jaworowski if (bus_activate_resource(child, type, *rid, res)) { 546db5ef4fcSRafal Jaworowski rman_release_resource(res); 547db5ef4fcSRafal Jaworowski return (NULL); 548db5ef4fcSRafal Jaworowski } 549db5ef4fcSRafal Jaworowski 550db5ef4fcSRafal Jaworowski return (res); 551db5ef4fcSRafal Jaworowski } 552db5ef4fcSRafal Jaworowski 553db5ef4fcSRafal Jaworowski static int 554db5ef4fcSRafal Jaworowski mv_pcib_release_resource(device_t dev, device_t child, int type, int rid, 555db5ef4fcSRafal Jaworowski struct resource *res) 556db5ef4fcSRafal Jaworowski { 557db5ef4fcSRafal Jaworowski 558db5ef4fcSRafal Jaworowski if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY) 559db5ef4fcSRafal Jaworowski return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child, 560db5ef4fcSRafal Jaworowski type, rid, res)); 561db5ef4fcSRafal Jaworowski 562db5ef4fcSRafal Jaworowski return (rman_release_resource(res)); 563db5ef4fcSRafal Jaworowski } 564db5ef4fcSRafal Jaworowski 565db5ef4fcSRafal Jaworowski static int 566db5ef4fcSRafal Jaworowski mv_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 567db5ef4fcSRafal Jaworowski { 568db5ef4fcSRafal Jaworowski struct mv_pcib_softc *sc = device_get_softc(dev); 569db5ef4fcSRafal Jaworowski 570db5ef4fcSRafal Jaworowski switch (which) { 571db5ef4fcSRafal Jaworowski case PCIB_IVAR_BUS: 572db5ef4fcSRafal Jaworowski *result = sc->sc_busnr; 573db5ef4fcSRafal Jaworowski return (0); 574db5ef4fcSRafal Jaworowski case PCIB_IVAR_DOMAIN: 575db5ef4fcSRafal Jaworowski *result = device_get_unit(dev); 576db5ef4fcSRafal Jaworowski return (0); 577db5ef4fcSRafal Jaworowski } 578db5ef4fcSRafal Jaworowski 579db5ef4fcSRafal Jaworowski return (ENOENT); 580db5ef4fcSRafal Jaworowski } 581db5ef4fcSRafal Jaworowski 582db5ef4fcSRafal Jaworowski static int 583db5ef4fcSRafal Jaworowski mv_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 584db5ef4fcSRafal Jaworowski { 585db5ef4fcSRafal Jaworowski struct mv_pcib_softc *sc = device_get_softc(dev); 586db5ef4fcSRafal Jaworowski 587db5ef4fcSRafal Jaworowski switch (which) { 588db5ef4fcSRafal Jaworowski case PCIB_IVAR_BUS: 589db5ef4fcSRafal Jaworowski sc->sc_busnr = value; 590db5ef4fcSRafal Jaworowski return (0); 591db5ef4fcSRafal Jaworowski } 592db5ef4fcSRafal Jaworowski 593db5ef4fcSRafal Jaworowski return (ENOENT); 594db5ef4fcSRafal Jaworowski } 595db5ef4fcSRafal Jaworowski 596db5ef4fcSRafal Jaworowski static inline void 597db5ef4fcSRafal Jaworowski pcib_write_irq_mask(struct mv_pcib_softc *sc, uint32_t mask) 598db5ef4fcSRafal Jaworowski { 599db5ef4fcSRafal Jaworowski 600db5ef4fcSRafal Jaworowski if (!sc->sc_type != MV_TYPE_PCI) 601db5ef4fcSRafal Jaworowski return; 602db5ef4fcSRafal Jaworowski 603db5ef4fcSRafal Jaworowski bus_space_write_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_IRQ_MASK, mask); 604db5ef4fcSRafal Jaworowski } 605db5ef4fcSRafal Jaworowski 606db5ef4fcSRafal Jaworowski static void 607db5ef4fcSRafal Jaworowski mv_pcib_hw_cfginit(void) 6086975124cSRafal Jaworowski { 6096975124cSRafal Jaworowski static int opened = 0; 6106975124cSRafal Jaworowski 6116975124cSRafal Jaworowski if (opened) 6126975124cSRafal Jaworowski return; 6136975124cSRafal Jaworowski 6146975124cSRafal Jaworowski mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN); 6156975124cSRafal Jaworowski opened = 1; 6166975124cSRafal Jaworowski } 6176975124cSRafal Jaworowski 6186975124cSRafal Jaworowski static uint32_t 619db5ef4fcSRafal Jaworowski mv_pcib_hw_cfgread(struct mv_pcib_softc *sc, u_int bus, u_int slot, 6206975124cSRafal Jaworowski u_int func, u_int reg, int bytes) 6216975124cSRafal Jaworowski { 6226975124cSRafal Jaworowski uint32_t addr, data, ca, cd; 6236975124cSRafal Jaworowski 624db5ef4fcSRafal Jaworowski ca = (sc->sc_type != MV_TYPE_PCI) ? 6256975124cSRafal Jaworowski PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR; 626db5ef4fcSRafal Jaworowski cd = (sc->sc_type != MV_TYPE_PCI) ? 6276975124cSRafal Jaworowski PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA; 6286975124cSRafal Jaworowski addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) | 6296975124cSRafal Jaworowski PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg); 6306975124cSRafal Jaworowski 6316975124cSRafal Jaworowski mtx_lock_spin(&pcicfg_mtx); 6326975124cSRafal Jaworowski bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr); 6336975124cSRafal Jaworowski 6346975124cSRafal Jaworowski data = ~0; 6356975124cSRafal Jaworowski switch (bytes) { 6366975124cSRafal Jaworowski case 1: 6376975124cSRafal Jaworowski data = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 6386975124cSRafal Jaworowski cd + (reg & 3)); 6396975124cSRafal Jaworowski break; 6406975124cSRafal Jaworowski case 2: 6416975124cSRafal Jaworowski data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh, 6426975124cSRafal Jaworowski cd + (reg & 2))); 6436975124cSRafal Jaworowski break; 6446975124cSRafal Jaworowski case 4: 6456975124cSRafal Jaworowski data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh, 6466975124cSRafal Jaworowski cd)); 6476975124cSRafal Jaworowski break; 6486975124cSRafal Jaworowski } 6496975124cSRafal Jaworowski mtx_unlock_spin(&pcicfg_mtx); 6506975124cSRafal Jaworowski return (data); 6516975124cSRafal Jaworowski } 6526975124cSRafal Jaworowski 6536975124cSRafal Jaworowski static void 654db5ef4fcSRafal Jaworowski mv_pcib_hw_cfgwrite(struct mv_pcib_softc *sc, u_int bus, u_int slot, 6556975124cSRafal Jaworowski u_int func, u_int reg, uint32_t data, int bytes) 6566975124cSRafal Jaworowski { 6576975124cSRafal Jaworowski uint32_t addr, ca, cd; 6586975124cSRafal Jaworowski 659db5ef4fcSRafal Jaworowski ca = (sc->sc_type != MV_TYPE_PCI) ? 6606975124cSRafal Jaworowski PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR; 661db5ef4fcSRafal Jaworowski cd = (sc->sc_type != MV_TYPE_PCI) ? 6626975124cSRafal Jaworowski PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA; 6636975124cSRafal Jaworowski addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) | 6646975124cSRafal Jaworowski PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg); 6656975124cSRafal Jaworowski 6666975124cSRafal Jaworowski mtx_lock_spin(&pcicfg_mtx); 6676975124cSRafal Jaworowski bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr); 6686975124cSRafal Jaworowski 6696975124cSRafal Jaworowski switch (bytes) { 6706975124cSRafal Jaworowski case 1: 6716975124cSRafal Jaworowski bus_space_write_1(sc->sc_bst, sc->sc_bsh, 6726975124cSRafal Jaworowski cd + (reg & 3), data); 6736975124cSRafal Jaworowski break; 6746975124cSRafal Jaworowski case 2: 6756975124cSRafal Jaworowski bus_space_write_2(sc->sc_bst, sc->sc_bsh, 6766975124cSRafal Jaworowski cd + (reg & 2), htole16(data)); 6776975124cSRafal Jaworowski break; 6786975124cSRafal Jaworowski case 4: 6796975124cSRafal Jaworowski bus_space_write_4(sc->sc_bst, sc->sc_bsh, 6806975124cSRafal Jaworowski cd, htole32(data)); 6816975124cSRafal Jaworowski break; 6826975124cSRafal Jaworowski } 6836975124cSRafal Jaworowski mtx_unlock_spin(&pcicfg_mtx); 6846975124cSRafal Jaworowski } 6856975124cSRafal Jaworowski 6866975124cSRafal Jaworowski static int 687db5ef4fcSRafal Jaworowski mv_pcib_maxslots(device_t dev) 6886975124cSRafal Jaworowski { 689db5ef4fcSRafal Jaworowski struct mv_pcib_softc *sc = device_get_softc(dev); 6906975124cSRafal Jaworowski 691db5ef4fcSRafal Jaworowski return ((sc->sc_type != MV_TYPE_PCI) ? 1 : PCI_SLOTMAX); 6926975124cSRafal Jaworowski } 6936975124cSRafal Jaworowski 6946975124cSRafal Jaworowski static uint32_t 695db5ef4fcSRafal Jaworowski mv_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, 6966975124cSRafal Jaworowski u_int reg, int bytes) 6976975124cSRafal Jaworowski { 698db5ef4fcSRafal Jaworowski struct mv_pcib_softc *sc = device_get_softc(dev); 6996975124cSRafal Jaworowski 7006975124cSRafal Jaworowski /* Skip self */ 7016975124cSRafal Jaworowski if (bus == sc->sc_busnr && slot == sc->sc_devnr) 7026975124cSRafal Jaworowski return (~0U); 7036975124cSRafal Jaworowski 704db5ef4fcSRafal Jaworowski return (mv_pcib_hw_cfgread(sc, bus, slot, func, reg, bytes)); 7056975124cSRafal Jaworowski } 7066975124cSRafal Jaworowski 7076975124cSRafal Jaworowski static void 708db5ef4fcSRafal Jaworowski mv_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, 7096975124cSRafal Jaworowski u_int reg, uint32_t val, int bytes) 7106975124cSRafal Jaworowski { 711db5ef4fcSRafal Jaworowski struct mv_pcib_softc *sc = device_get_softc(dev); 7126975124cSRafal Jaworowski 7136975124cSRafal Jaworowski /* Skip self */ 7146975124cSRafal Jaworowski if (bus == sc->sc_busnr && slot == sc->sc_devnr) 7156975124cSRafal Jaworowski return; 7166975124cSRafal Jaworowski 717db5ef4fcSRafal Jaworowski mv_pcib_hw_cfgwrite(sc, bus, slot, func, reg, val, bytes); 7186975124cSRafal Jaworowski } 7196975124cSRafal Jaworowski 720db5ef4fcSRafal Jaworowski static int 721db5ef4fcSRafal Jaworowski mv_pcib_route_interrupt(device_t pcib, device_t dev, int pin) 7226975124cSRafal Jaworowski { 723db5ef4fcSRafal Jaworowski struct mv_pcib_softc *sc; 724db5ef4fcSRafal Jaworowski int err, interrupt; 725db5ef4fcSRafal Jaworowski 726db5ef4fcSRafal Jaworowski sc = device_get_softc(pcib); 727db5ef4fcSRafal Jaworowski 728db5ef4fcSRafal Jaworowski err = fdt_pci_route_intr(pci_get_bus(dev), pci_get_slot(dev), 729db5ef4fcSRafal Jaworowski pci_get_function(dev), pin, &sc->sc_intr_info, &interrupt); 730db5ef4fcSRafal Jaworowski if (err == 0) 731db5ef4fcSRafal Jaworowski return (interrupt); 732db5ef4fcSRafal Jaworowski 733db5ef4fcSRafal Jaworowski device_printf(pcib, "could not route pin %d for device %d.%d\n", 734db5ef4fcSRafal Jaworowski pin, pci_get_slot(dev), pci_get_function(dev)); 735db5ef4fcSRafal Jaworowski return (PCI_INVALID_IRQ); 736db5ef4fcSRafal Jaworowski } 737db5ef4fcSRafal Jaworowski 738db5ef4fcSRafal Jaworowski static int 739db5ef4fcSRafal Jaworowski mv_pcib_decode_win(phandle_t node, struct mv_pcib_softc *sc) 740db5ef4fcSRafal Jaworowski { 741db5ef4fcSRafal Jaworowski struct fdt_pci_range io_space, mem_space; 742db5ef4fcSRafal Jaworowski device_t dev; 7436975124cSRafal Jaworowski int error; 7446975124cSRafal Jaworowski 745db5ef4fcSRafal Jaworowski dev = sc->sc_dev; 746db5ef4fcSRafal Jaworowski 747db5ef4fcSRafal Jaworowski if ((error = fdt_pci_ranges(node, &io_space, &mem_space)) != 0) { 748db5ef4fcSRafal Jaworowski device_printf(dev, "could not retrieve 'ranges' data\n"); 749db5ef4fcSRafal Jaworowski return (error); 750db5ef4fcSRafal Jaworowski } 751db5ef4fcSRafal Jaworowski 7526975124cSRafal Jaworowski /* Configure CPU decoding windows */ 753db5ef4fcSRafal Jaworowski error = decode_win_cpu_set(sc->sc_io_win_target, 754db5ef4fcSRafal Jaworowski sc->sc_io_win_attr, io_space.base_parent, io_space.len, -1); 7556975124cSRafal Jaworowski if (error < 0) { 756db5ef4fcSRafal Jaworowski device_printf(dev, "could not set up CPU decode " 7576975124cSRafal Jaworowski "window for PCI IO\n"); 758db5ef4fcSRafal Jaworowski return (ENXIO); 7596975124cSRafal Jaworowski } 760db5ef4fcSRafal Jaworowski error = decode_win_cpu_set(sc->sc_mem_win_target, 761db5ef4fcSRafal Jaworowski sc->sc_mem_win_attr, mem_space.base_parent, mem_space.len, -1); 7626975124cSRafal Jaworowski if (error < 0) { 763db5ef4fcSRafal Jaworowski device_printf(dev, "could not set up CPU decode " 7646975124cSRafal Jaworowski "windows for PCI MEM\n"); 765db5ef4fcSRafal Jaworowski return (ENXIO); 7666975124cSRafal Jaworowski } 7676975124cSRafal Jaworowski 768db5ef4fcSRafal Jaworowski sc->sc_io_base = io_space.base_parent; 769db5ef4fcSRafal Jaworowski sc->sc_io_size = io_space.len; 770db5ef4fcSRafal Jaworowski 771db5ef4fcSRafal Jaworowski sc->sc_mem_base = mem_space.base_parent; 772db5ef4fcSRafal Jaworowski sc->sc_mem_size = mem_space.len; 773db5ef4fcSRafal Jaworowski 774db5ef4fcSRafal Jaworowski return (0); 7756975124cSRafal Jaworowski } 7766975124cSRafal Jaworowski 777db5ef4fcSRafal Jaworowski static int 778db5ef4fcSRafal Jaworowski mv_pcib_intr_info(phandle_t node, struct mv_pcib_softc *sc) 7796975124cSRafal Jaworowski { 780db5ef4fcSRafal Jaworowski int error; 7816975124cSRafal Jaworowski 782db5ef4fcSRafal Jaworowski if ((error = fdt_pci_intr_info(node, &sc->sc_intr_info)) != 0) 783db5ef4fcSRafal Jaworowski return (error); 7846975124cSRafal Jaworowski 785db5ef4fcSRafal Jaworowski return (0); 7866975124cSRafal Jaworowski } 7876975124cSRafal Jaworowski 788db5ef4fcSRafal Jaworowski #if 0 7896975124cSRafal Jaworowski control = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 7906975124cSRafal Jaworowski PCIE_REG_CONTROL); 7916975124cSRafal Jaworowski 7926975124cSRafal Jaworowski /* 7936975124cSRafal Jaworowski * If this PCI-E port (controller) is configured (by the 7946975124cSRafal Jaworowski * underlying firmware) with lane width other than 1x, there 7956975124cSRafal Jaworowski * are auxiliary resources defined for aggregating more width 7966975124cSRafal Jaworowski * on our lane. Skip all such entries as they are not 7976975124cSRafal Jaworowski * standalone ports and must not have a device object 7986975124cSRafal Jaworowski * instantiated. 7996975124cSRafal Jaworowski */ 8006975124cSRafal Jaworowski if ((control & PCIE_CTRL_LINK1X) == 0) 8016975124cSRafal Jaworowski while (info->op_base && 8026975124cSRafal Jaworowski info->op_type == MV_TYPE_PCIE_AGGR_LANE) 8036975124cSRafal Jaworowski info++; 8046975124cSRafal Jaworowski 805db5ef4fcSRafal Jaworowski mv_pcib_add_child(driver, parent, sc); 806db5ef4fcSRafal Jaworowski #endif 807