1117119Stmm/*- 2117119Stmm * Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier 3117119Stmm * Copyright (c) 2000 Michael Smith <msmith@freebsd.org> 4117119Stmm * Copyright (c) 2000 BSDi 5117119Stmm * Copyright (c) 2001 - 2003 Thomas Moestl <tmm@FreeBSD.org> 6200987Smarius * Copyright (c) 2009 by Marius Strobl <marius@FreeBSD.org> 7117119Stmm * All rights reserved. 8117119Stmm * 9117119Stmm * Redistribution and use in source and binary forms, with or without 10117119Stmm * modification, are permitted provided that the following conditions 11117119Stmm * are met: 12117119Stmm * 1. Redistributions of source code must retain the above copyright 13117119Stmm * notice, this list of conditions and the following disclaimer. 14117119Stmm * 2. Redistributions in binary form must reproduce the above copyright 15117119Stmm * notice, this list of conditions and the following disclaimer in the 16117119Stmm * documentation and/or other materials provided with the distribution. 17117119Stmm * 3. The name of the author may not be used to endorse or promote products 18117119Stmm * derived from this software without specific prior written permission. 19117119Stmm * 20117119Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21117119Stmm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22117119Stmm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23117119Stmm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24117119Stmm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25117119Stmm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26117119Stmm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27117119Stmm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28117119Stmm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29117119Stmm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30117119Stmm * SUCH DAMAGE. 31117119Stmm * 32117119Stmm * from: FreeBSD: src/sys/dev/pci/pci_pci.c,v 1.3 2000/12/13 33117119Stmm */ 34117119Stmm 35153059Smarius#include <sys/cdefs.h> 36153059Smarius__FBSDID("$FreeBSD: releng/11.0/sys/sparc64/pci/ofw_pcib.c 298711 2016-04-27 16:39:05Z jhb $"); 37153059Smarius 38117119Stmm#include "opt_ofw_pci.h" 39117119Stmm 40117119Stmm#include <sys/param.h> 41200987Smarius#include <sys/bus.h> 42117119Stmm#include <sys/kernel.h> 43200987Smarius#include <sys/libkern.h> 44117119Stmm#include <sys/module.h> 45221393Sjhb#include <sys/rman.h> 46117119Stmm 47133589Smarius#include <dev/ofw/ofw_bus.h> 48117119Stmm#include <dev/ofw/openfirm.h> 49117119Stmm 50117119Stmm#include <dev/pci/pcireg.h> 51117119Stmm#include <dev/pci/pcivar.h> 52117119Stmm#include <dev/pci/pcib_private.h> 53117119Stmm 54117119Stmm#include "pcib_if.h" 55117119Stmm 56117119Stmm#include <sparc64/pci/ofw_pci.h> 57117119Stmm#include <sparc64/pci/ofw_pcib_subr.h> 58117119Stmm 59247573Smarius#define PCI_DEVID_ALI_M5249 0x524910b9 60247573Smarius#define PCI_VENDOR_PLX 0x10b5 61247573Smarius 62117119Stmmstatic device_probe_t ofw_pcib_probe; 63117119Stmmstatic device_attach_t ofw_pcib_attach; 64247573Smariusstatic ofw_pci_setup_device_t ofw_pcib_setup_device; 65117119Stmm 66117119Stmmstatic device_method_t ofw_pcib_methods[] = { 67117119Stmm /* Device interface */ 68117119Stmm DEVMETHOD(device_probe, ofw_pcib_probe), 69117119Stmm DEVMETHOD(device_attach, ofw_pcib_attach), 70117119Stmm 71117119Stmm /* Bus interface */ 72117119Stmm 73117119Stmm /* pcib interface */ 74216962Smarius DEVMETHOD(pcib_route_interrupt, ofw_pcib_gen_route_interrupt), 75117119Stmm 76133589Smarius /* ofw_bus interface */ 77133589Smarius DEVMETHOD(ofw_bus_get_node, ofw_pcib_gen_get_node), 78247573Smarius DEVMETHOD(ofw_pci_setup_device, ofw_pcib_setup_device), 79133589Smarius 80227848Smarius DEVMETHOD_END 81117119Stmm}; 82117119Stmm 83154079Sjhbstatic devclass_t pcib_devclass; 84117119Stmm 85216962SmariusDEFINE_CLASS_1(pcib, ofw_pcib_driver, ofw_pcib_methods, 86216962Smarius sizeof(struct ofw_pcib_gen_softc), pcib_driver); 87247573SmariusEARLY_DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_driver, pcib_devclass, NULL, NULL, 88200874Smarius BUS_PASS_BUS); 89200815SmariusMODULE_DEPEND(ofw_pcib, pci, 1, 1, 1); 90117119Stmm 91117119Stmmstatic int 92117119Stmmofw_pcib_probe(device_t dev) 93117119Stmm{ 94200987Smarius char desc[sizeof("OFW PCIe-PCIe bridge")]; 95200987Smarius const char *dtype, *pbdtype; 96170929Smarius 97200987Smarius#define ISDTYPE(dtype, type) \ 98200987Smarius (((dtype) != NULL) && strcmp((dtype), (type)) == 0) 99200987Smarius 100117119Stmm if ((pci_get_class(dev) == PCIC_BRIDGE) && 101117119Stmm (pci_get_subclass(dev) == PCIS_BRIDGE_PCI) && 102133589Smarius ofw_bus_get_node(dev) != 0) { 103200987Smarius dtype = ofw_bus_get_type(dev); 104200987Smarius pbdtype = ofw_bus_get_type(device_get_parent( 105200987Smarius device_get_parent(dev))); 106200987Smarius snprintf(desc, sizeof(desc), "OFW PCI%s-PCI%s bridge", 107200987Smarius ISDTYPE(pbdtype, OFW_TYPE_PCIE) ? "e" : "", 108200987Smarius ISDTYPE(dtype, OFW_TYPE_PCIE) ? "e" : ""); 109200987Smarius device_set_desc_copy(dev, desc); 110247573Smarius return (BUS_PROBE_DEFAULT); 111117119Stmm } 112200987Smarius 113200987Smarius#undef ISDTYPE 114200987Smarius 115117119Stmm return (ENXIO); 116117119Stmm} 117117119Stmm 118117119Stmmstatic int 119117119Stmmofw_pcib_attach(device_t dev) 120117119Stmm{ 121200987Smarius struct ofw_pcib_gen_softc *sc; 122117119Stmm 123200987Smarius sc = device_get_softc(dev); 124200987Smarius 125200987Smarius switch (pci_get_devid(dev)) { 126200987Smarius /* 127200987Smarius * The ALi M5249 found in Fire-based machines by definition must me 128200987Smarius * subtractive as they have a ISA bridge on their secondary side but 129200987Smarius * don't indicate this in the class code although the ISA I/O range 130200987Smarius * isn't included in their bridge decode. 131200987Smarius */ 132247573Smarius case PCI_DEVID_ALI_M5249: 133200987Smarius sc->ops_pcib_sc.flags |= PCIB_SUBTRACTIVE; 134200987Smarius break; 135200987Smarius } 136200987Smarius 137247573Smarius switch (pci_get_vendor(dev)) { 138247573Smarius /* 139247573Smarius * Concurrently write the primary and secondary bus numbers in order 140247573Smarius * to work around a bug in PLX PEX 8114 causing the internal shadow 141247573Smarius * copies of these not to be updated when setting them bytewise. 142247573Smarius */ 143247573Smarius case PCI_VENDOR_PLX: 144247573Smarius pci_write_config(dev, PCIR_PRIBUS_1, 145247573Smarius pci_read_config(dev, PCIR_SECBUS_1, 1) << 8 | 146247573Smarius pci_read_config(dev, PCIR_PRIBUS_1, 1), 2); 147247573Smarius break; 148247573Smarius } 149247573Smarius 150117119Stmm ofw_pcib_gen_setup(dev); 151117119Stmm pcib_attach_common(dev); 152298711Sjhb return (pcib_attach_child(dev)); 153117119Stmm} 154247573Smarius 155247573Smariusstatic void 156247573Smariusofw_pcib_setup_device(device_t bus, device_t child) 157247573Smarius{ 158247573Smarius int i; 159247573Smarius uint16_t reg; 160247573Smarius 161247573Smarius switch (pci_get_vendor(bus)) { 162247573Smarius /* 163247573Smarius * For PLX PEX 8532 issue 64 TLPs to the child from the downstream 164247573Smarius * port to the child device in order to work around a hardware bug. 165247573Smarius */ 166247573Smarius case PCI_VENDOR_PLX: 167247573Smarius for (i = 0, reg = 0; i < 64; i++) 168247573Smarius reg |= pci_get_devid(child); 169247573Smarius break; 170247573Smarius } 171247573Smarius 172247573Smarius OFW_PCI_SETUP_DEVICE(device_get_parent(bus), child); 173247573Smarius} 174