1/*- 2 * Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier 3 * Copyright (c) 2000 Michael Smith <msmith@freebsd.org> 4 * Copyright (c) 2000 BSDi 5 * Copyright (c) 2001 - 2003 Thomas Moestl <tmm@FreeBSD.org> 6 * Copyright (c) 2009 by Marius Strobl <marius@FreeBSD.org> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * from: FreeBSD: src/sys/dev/pci/pci_pci.c,v 1.3 2000/12/13 33 */ 34 35#include <sys/cdefs.h> 36__FBSDID("$FreeBSD: releng/11.0/sys/sparc64/pci/ofw_pcib.c 298711 2016-04-27 16:39:05Z jhb $"); 37 38#include "opt_ofw_pci.h" 39 40#include <sys/param.h> 41#include <sys/bus.h> 42#include <sys/kernel.h> 43#include <sys/libkern.h> 44#include <sys/module.h> 45#include <sys/rman.h> 46 47#include <dev/ofw/ofw_bus.h> 48#include <dev/ofw/openfirm.h> 49 50#include <dev/pci/pcireg.h> 51#include <dev/pci/pcivar.h> 52#include <dev/pci/pcib_private.h> 53 54#include "pcib_if.h" 55 56#include <sparc64/pci/ofw_pci.h> 57#include <sparc64/pci/ofw_pcib_subr.h> 58 59#define PCI_DEVID_ALI_M5249 0x524910b9 60#define PCI_VENDOR_PLX 0x10b5 61 62static device_probe_t ofw_pcib_probe; 63static device_attach_t ofw_pcib_attach; 64static ofw_pci_setup_device_t ofw_pcib_setup_device; 65 66static device_method_t ofw_pcib_methods[] = { 67 /* Device interface */ 68 DEVMETHOD(device_probe, ofw_pcib_probe), 69 DEVMETHOD(device_attach, ofw_pcib_attach), 70 71 /* Bus interface */ 72 73 /* pcib interface */ 74 DEVMETHOD(pcib_route_interrupt, ofw_pcib_gen_route_interrupt), 75 76 /* ofw_bus interface */ 77 DEVMETHOD(ofw_bus_get_node, ofw_pcib_gen_get_node), 78 DEVMETHOD(ofw_pci_setup_device, ofw_pcib_setup_device), 79 80 DEVMETHOD_END 81}; 82 83static devclass_t pcib_devclass; 84 85DEFINE_CLASS_1(pcib, ofw_pcib_driver, ofw_pcib_methods, 86 sizeof(struct ofw_pcib_gen_softc), pcib_driver); 87EARLY_DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_driver, pcib_devclass, NULL, NULL, 88 BUS_PASS_BUS); 89MODULE_DEPEND(ofw_pcib, pci, 1, 1, 1); 90 91static int 92ofw_pcib_probe(device_t dev) 93{ 94 char desc[sizeof("OFW PCIe-PCIe bridge")]; 95 const char *dtype, *pbdtype; 96 97#define ISDTYPE(dtype, type) \ 98 (((dtype) != NULL) && strcmp((dtype), (type)) == 0) 99 100 if ((pci_get_class(dev) == PCIC_BRIDGE) && 101 (pci_get_subclass(dev) == PCIS_BRIDGE_PCI) && 102 ofw_bus_get_node(dev) != 0) { 103 dtype = ofw_bus_get_type(dev); 104 pbdtype = ofw_bus_get_type(device_get_parent( 105 device_get_parent(dev))); 106 snprintf(desc, sizeof(desc), "OFW PCI%s-PCI%s bridge", 107 ISDTYPE(pbdtype, OFW_TYPE_PCIE) ? "e" : "", 108 ISDTYPE(dtype, OFW_TYPE_PCIE) ? "e" : ""); 109 device_set_desc_copy(dev, desc); 110 return (BUS_PROBE_DEFAULT); 111 } 112 113#undef ISDTYPE 114 115 return (ENXIO); 116} 117 118static int 119ofw_pcib_attach(device_t dev) 120{ 121 struct ofw_pcib_gen_softc *sc; 122 123 sc = device_get_softc(dev); 124 125 switch (pci_get_devid(dev)) { 126 /* 127 * The ALi M5249 found in Fire-based machines by definition must me 128 * subtractive as they have a ISA bridge on their secondary side but 129 * don't indicate this in the class code although the ISA I/O range 130 * isn't included in their bridge decode. 131 */ 132 case PCI_DEVID_ALI_M5249: 133 sc->ops_pcib_sc.flags |= PCIB_SUBTRACTIVE; 134 break; 135 } 136 137 switch (pci_get_vendor(dev)) { 138 /* 139 * Concurrently write the primary and secondary bus numbers in order 140 * to work around a bug in PLX PEX 8114 causing the internal shadow 141 * copies of these not to be updated when setting them bytewise. 142 */ 143 case PCI_VENDOR_PLX: 144 pci_write_config(dev, PCIR_PRIBUS_1, 145 pci_read_config(dev, PCIR_SECBUS_1, 1) << 8 | 146 pci_read_config(dev, PCIR_PRIBUS_1, 1), 2); 147 break; 148 } 149 150 ofw_pcib_gen_setup(dev); 151 pcib_attach_common(dev); 152 return (pcib_attach_child(dev)); 153} 154 155static void 156ofw_pcib_setup_device(device_t bus, device_t child) 157{ 158 int i; 159 uint16_t reg; 160 161 switch (pci_get_vendor(bus)) { 162 /* 163 * For PLX PEX 8532 issue 64 TLPs to the child from the downstream 164 * port to the child device in order to work around a hardware bug. 165 */ 166 case PCI_VENDOR_PLX: 167 for (i = 0, reg = 0; i < 64; i++) 168 reg |= pci_get_devid(child); 169 break; 170 } 171 172 OFW_PCI_SETUP_DEVICE(device_get_parent(bus), child); 173} 174