1117119Stmm/*- 2117119Stmm * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3117119Stmm * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 4117119Stmm * Copyright (c) 2000, BSDi 5117119Stmm * Copyright (c) 2003, Thomas Moestl <tmm@FreeBSD.org> 6200921Smarius * Copyright (c) 2005 - 2009 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 unmodified, this list of conditions, and the following 14117119Stmm * disclaimer. 15117119Stmm * 2. Redistributions in binary form must reproduce the above copyright 16117119Stmm * notice, this list of conditions and the following disclaimer in the 17117119Stmm * documentation and/or other materials provided with the distribution. 18117119Stmm * 19117119Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20117119Stmm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21117119Stmm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22117119Stmm * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23117119Stmm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24117119Stmm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25117119Stmm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26117119Stmm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27117119Stmm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28117119Stmm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29117119Stmm */ 30117119Stmm 31152684Smarius#include <sys/cdefs.h> 32152684Smarius__FBSDID("$FreeBSD: releng/10.2/sys/sparc64/pci/ofw_pcibus.c 233018 2012-03-15 22:53:39Z nwhitehorn $"); 33152684Smarius 34117119Stmm#include "opt_ofw_pci.h" 35133589Smarius 36117119Stmm#include <sys/param.h> 37117119Stmm#include <sys/bus.h> 38117119Stmm#include <sys/kernel.h> 39117119Stmm#include <sys/libkern.h> 40117119Stmm#include <sys/module.h> 41117119Stmm#include <sys/pciio.h> 42117119Stmm 43133589Smarius#include <dev/ofw/ofw_bus.h> 44133589Smarius#include <dev/ofw/ofw_pci.h> 45117119Stmm#include <dev/ofw/openfirm.h> 46117119Stmm 47117119Stmm#include <machine/bus.h> 48178728Smarius#ifndef SUN4V 49117119Stmm#include <machine/bus_common.h> 50169793Smarius#include <machine/iommureg.h> 51163146Skmacy#endif 52117119Stmm#include <machine/resource.h> 53117119Stmm 54117119Stmm#include <dev/pci/pcireg.h> 55117119Stmm#include <dev/pci/pcivar.h> 56117119Stmm#include <dev/pci/pci_private.h> 57117119Stmm 58117119Stmm#include <sparc64/pci/ofw_pci.h> 59117119Stmm 60117119Stmm#include "pcib_if.h" 61117119Stmm#include "pci_if.h" 62117119Stmm 63182020Smarius/* Helper functions */ 64182108Smariusstatic void ofw_pcibus_setup_device(device_t bridge, uint32_t clock, 65182108Smarius u_int busno, u_int slot, u_int func); 66117119Stmm 67182020Smarius/* Methods */ 68200920Smariusstatic bus_child_pnpinfo_str_t ofw_pcibus_pnpinfo_str; 69200920Smariusstatic device_attach_t ofw_pcibus_attach; 70117119Stmmstatic device_probe_t ofw_pcibus_probe; 71200920Smariusstatic ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo; 72117119Stmmstatic pci_assign_interrupt_t ofw_pcibus_assign_interrupt; 73117119Stmm 74117119Stmmstatic device_method_t ofw_pcibus_methods[] = { 75117119Stmm /* Device interface */ 76117119Stmm DEVMETHOD(device_probe, ofw_pcibus_probe), 77117119Stmm DEVMETHOD(device_attach, ofw_pcibus_attach), 78117119Stmm 79117119Stmm /* Bus interface */ 80190113Smarius DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_pnpinfo_str), 81117119Stmm 82117119Stmm /* PCI interface */ 83117119Stmm DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt), 84117119Stmm 85133589Smarius /* ofw_bus interface */ 86152684Smarius DEVMETHOD(ofw_bus_get_devinfo, ofw_pcibus_get_devinfo), 87152684Smarius DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 88152684Smarius DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 89152684Smarius DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 90152684Smarius DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 91152684Smarius DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 92117119Stmm 93227848Smarius DEVMETHOD_END 94117119Stmm}; 95117119Stmm 96117119Stmmstruct ofw_pcibus_devinfo { 97117119Stmm struct pci_devinfo opd_dinfo; 98152684Smarius struct ofw_bus_devinfo opd_obdinfo; 99117119Stmm}; 100117119Stmm 101154600Sjhbstatic devclass_t pci_devclass; 102117119Stmm 103232403SjhbDEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods, 104232403Sjhb sizeof(struct pci_softc), pci_driver); 105200874SmariusEARLY_DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0, 106200874Smarius BUS_PASS_BUS); 107117119StmmMODULE_VERSION(ofw_pcibus, 1); 108117119StmmMODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1); 109117119Stmm 110117119Stmmstatic int 111117119Stmmofw_pcibus_probe(device_t dev) 112117119Stmm{ 113117119Stmm 114233018Snwhitehorn if (ofw_bus_get_node(dev) == -1) 115117119Stmm return (ENXIO); 116117119Stmm device_set_desc(dev, "OFW PCI bus"); 117117119Stmm 118117119Stmm return (0); 119117119Stmm} 120117119Stmm 121117119Stmm/* 122117119Stmm * Perform miscellaneous setups the firmware usually does not do for us. 123117119Stmm */ 124117119Stmmstatic void 125182108Smariusofw_pcibus_setup_device(device_t bridge, uint32_t clock, u_int busno, 126182108Smarius u_int slot, u_int func) 127117119Stmm{ 128200920Smarius#define CS_READ(n, w) \ 129200920Smarius PCIB_READ_CONFIG(bridge, busno, slot, func, (n), (w)) 130200920Smarius#define CS_WRITE(n, v, w) \ 131200920Smarius PCIB_WRITE_CONFIG(bridge, busno, slot, func, (n), (v), (w)) 132200920Smarius 133182108Smarius#ifndef SUN4V 134172333Smarius uint32_t reg; 135172333Smarius 136117119Stmm /* 137182020Smarius * Initialize the latency timer register for busmaster devices to 138182020Smarius * work properly. This is another task which the firmware doesn't 139182020Smarius * always perform. The Min_Gnt register can be used to compute its 140182020Smarius * recommended value: it contains the desired latency in units of 141182108Smarius * 1/4 us assuming a clock rate of 33MHz. To calculate the correct 142182108Smarius * latency timer value, the clock frequency of the bus (defaulting 143182108Smarius * to 33MHz) should be used and no wait states assumed. 144182108Smarius * For bridges, we additionally set up the bridge control and the 145182108Smarius * secondary latency registers. 146117119Stmm */ 147200920Smarius if ((CS_READ(PCIR_HDRTYPE, 1) & PCIM_HDRTYPE) == 148200920Smarius PCIM_HDRTYPE_BRIDGE) { 149200920Smarius reg = CS_READ(PCIR_BRIDGECTL_1, 1); 150182108Smarius reg |= PCIB_BCR_MASTER_ABORT_MODE | PCIB_BCR_SERR_ENABLE | 151182108Smarius PCIB_BCR_PERR_ENABLE; 152117119Stmm#ifdef OFW_PCI_DEBUG 153182108Smarius device_printf(bridge, 154182108Smarius "bridge %d/%d/%d: control 0x%x -> 0x%x\n", 155200920Smarius busno, slot, func, CS_READ(PCIR_BRIDGECTL_1, 1), reg); 156117119Stmm#endif /* OFW_PCI_DEBUG */ 157200920Smarius CS_WRITE(PCIR_BRIDGECTL_1, reg, 1); 158182108Smarius 159182108Smarius reg = OFW_PCI_LATENCY; 160182108Smarius#ifdef OFW_PCI_DEBUG 161182108Smarius device_printf(bridge, 162182108Smarius "bridge %d/%d/%d: latency timer %d -> %d\n", 163200920Smarius busno, slot, func, CS_READ(PCIR_SECLAT_1, 1), reg); 164182108Smarius#endif /* OFW_PCI_DEBUG */ 165200920Smarius CS_WRITE(PCIR_SECLAT_1, reg, 1); 166182108Smarius } else { 167200920Smarius reg = CS_READ(PCIR_MINGNT, 1); 168219780Smarius if ((int)reg > 0) { 169182108Smarius switch (clock) { 170182108Smarius case 33000000: 171182108Smarius reg *= 8; 172182108Smarius break; 173182108Smarius case 66000000: 174182108Smarius reg *= 4; 175182108Smarius break; 176182108Smarius } 177182108Smarius reg = min(reg, 255); 178182108Smarius } else 179182108Smarius reg = OFW_PCI_LATENCY; 180117119Stmm } 181182108Smarius#ifdef OFW_PCI_DEBUG 182182108Smarius device_printf(bridge, "device %d/%d/%d: latency timer %d -> %d\n", 183200920Smarius busno, slot, func, CS_READ(PCIR_LATTIMER, 1), reg); 184182108Smarius#endif /* OFW_PCI_DEBUG */ 185200920Smarius CS_WRITE(PCIR_LATTIMER, reg, 1); 186117119Stmm 187117119Stmm /* 188117119Stmm * Compute a value to write into the cache line size register. 189117119Stmm * The role of the streaming cache is unclear in write invalidate 190182020Smarius * transfers, so it is made sure that it's line size is always 191182020Smarius * reached. Generally, the cache line size is fixed at 64 bytes 192182020Smarius * by Fireplane/Safari, JBus and UPA. 193117119Stmm */ 194200920Smarius CS_WRITE(PCIR_CACHELNSZ, STRBUF_LINESZ / sizeof(uint32_t), 1); 195169793Smarius#endif 196117119Stmm 197117119Stmm /* 198200921Smarius * Ensure that ALi M5229 report the actual content of PCIR_PROGIF 199200921Smarius * and that IDE I/O is force enabled. The former is done in order 200200921Smarius * to have unique behavior across revisions as some default to 201200921Smarius * hiding bits 4-6 for compliance with PCI 2.3. The latter is done 202200921Smarius * as at least revision 0xc8 requires the PCIM_CMD_PORTEN bypass 203200921Smarius * to be always enabled as otherwise even enabling PCIM_CMD_PORTEN 204200921Smarius * results in an instant data access trap on Fire-based machines. 205200921Smarius * Thus these quirks have to be handled before pci(4) adds the maps. 206200921Smarius * Note that for older revisions bit 0 of register 0x50 enables the 207200921Smarius * internal IDE function instead of force enabling IDE I/O. 208200921Smarius */ 209200921Smarius if ((CS_READ(PCIR_VENDOR, 2) == 0x10b9 && 210200921Smarius CS_READ(PCIR_DEVICE, 2) == 0x5229)) 211200921Smarius CS_WRITE(0x50, CS_READ(0x50, 1) | 0x3, 1); 212200921Smarius 213200921Smarius /* 214182020Smarius * The preset in the intline register is usually wrong. Reset 215182020Smarius * it to 255, so that the PCI code will reroute the interrupt if 216182020Smarius * needed. 217117119Stmm */ 218200920Smarius CS_WRITE(PCIR_INTLINE, PCI_INVALID_IRQ, 1); 219200920Smarius 220200920Smarius#undef CS_READ 221200920Smarius#undef CS_WRITE 222117119Stmm} 223117119Stmm 224117119Stmmstatic int 225117119Stmmofw_pcibus_attach(device_t dev) 226117119Stmm{ 227153057Smarius device_t pcib; 228117119Stmm struct ofw_pci_register pcir; 229117119Stmm struct ofw_pcibus_devinfo *dinfo; 230117119Stmm phandle_t node, child; 231182108Smarius uint32_t clock; 232172394Smarius u_int busno, domain, func, slot; 233232403Sjhb int error; 234117119Stmm 235232403Sjhb error = pci_attach_common(dev); 236232403Sjhb if (error) 237232403Sjhb return (error); 238153057Smarius pcib = device_get_parent(dev); 239172394Smarius domain = pcib_get_domain(dev); 240117119Stmm busno = pcib_get_bus(dev); 241133589Smarius node = ofw_bus_get_node(dev); 242174117Smarius 243200921Smarius /* 244200921Smarius * Add the PCI side of the host-PCI bridge itself to the bus. 245200921Smarius * Note that we exclude the host-PCIe bridges here as these 246200921Smarius * have no configuration space implemented themselves. 247200921Smarius */ 248174117Smarius if (strcmp(device_get_name(device_get_parent(pcib)), "nexus") == 0 && 249200921Smarius ofw_bus_get_type(pcib) != NULL && 250200921Smarius strcmp(ofw_bus_get_type(pcib), OFW_TYPE_PCIE) != 0 && 251174117Smarius (dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, 252174117Smarius domain, busno, 0, 0, sizeof(*dinfo))) != NULL) { 253174117Smarius if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, node) != 0) 254174117Smarius pci_freecfg((struct pci_devinfo *)dinfo); 255174117Smarius else 256174117Smarius pci_add_child(dev, (struct pci_devinfo *)dinfo); 257174117Smarius } 258174117Smarius 259182108Smarius if (OF_getprop(ofw_bus_get_node(pcib), "clock-frequency", &clock, 260182108Smarius sizeof(clock)) == -1) 261182108Smarius clock = 33000000; 262117119Stmm for (child = OF_child(node); child != 0; child = OF_peer(child)) { 263152684Smarius if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1) 264140512Smarius continue; 265117119Stmm slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi); 266117119Stmm func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi); 267172394Smarius /* Some OFW device trees contain dupes. */ 268172394Smarius if (pci_find_dbsf(domain, busno, slot, func) != NULL) 269165885Smarius continue; 270182108Smarius ofw_pcibus_setup_device(pcib, clock, busno, slot, func); 271117119Stmm dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, 272172394Smarius domain, busno, slot, func, sizeof(*dinfo)); 273152684Smarius if (dinfo == NULL) 274152684Smarius continue; 275152684Smarius if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) != 276152684Smarius 0) { 277152684Smarius pci_freecfg((struct pci_devinfo *)dinfo); 278152684Smarius continue; 279152684Smarius } 280152684Smarius pci_add_child(dev, (struct pci_devinfo *)dinfo); 281220038Smarius OFW_PCI_SETUP_DEVICE(pcib, dinfo->opd_dinfo.cfg.dev); 282117119Stmm } 283117119Stmm 284117119Stmm return (bus_generic_attach(dev)); 285117119Stmm} 286117119Stmm 287117119Stmmstatic int 288117119Stmmofw_pcibus_assign_interrupt(device_t dev, device_t child) 289117119Stmm{ 290117119Stmm ofw_pci_intr_t intr; 291117119Stmm int isz; 292117119Stmm 293152684Smarius isz = OF_getprop(ofw_bus_get_node(child), "interrupts", &intr, 294152684Smarius sizeof(intr)); 295117119Stmm if (isz != sizeof(intr)) { 296117119Stmm /* No property; our best guess is the intpin. */ 297152684Smarius intr = pci_get_intpin(child); 298178728Smarius#ifndef SUN4V 299117119Stmm } else if (intr >= 255) { 300117119Stmm /* 301117119Stmm * A fully specified interrupt (including IGN), as present on 302182020Smarius * SPARCengine Ultra AX and E450. Extract the INO and return 303182020Smarius * it. 304117119Stmm */ 305117119Stmm return (INTINO(intr)); 306178728Smarius#endif 307117119Stmm } 308117119Stmm /* 309117119Stmm * If we got intr from a property, it may or may not be an intpin. 310117119Stmm * For on-board devices, it frequently is not, and is completely out 311182020Smarius * of the valid intpin range. For PCI slots, it hopefully is, 312182020Smarius * otherwise we will have trouble interfacing with non-OFW buses 313182020Smarius * such as cardbus. 314117119Stmm * Since we cannot tell which it is without violating layering, we 315182020Smarius * will always use the route_interrupt method, and treat exceptions 316182020Smarius * on the level they become apparent. 317117119Stmm */ 318117119Stmm return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr)); 319117119Stmm} 320117119Stmm 321152684Smariusstatic const struct ofw_bus_devinfo * 322152684Smariusofw_pcibus_get_devinfo(device_t bus, device_t dev) 323133589Smarius{ 324133589Smarius struct ofw_pcibus_devinfo *dinfo; 325133589Smarius 326133589Smarius dinfo = device_get_ivars(dev); 327152684Smarius return (&dinfo->opd_obdinfo); 328133589Smarius} 329186128Snwhitehorn 330186128Snwhitehornstatic int 331190113Smariusofw_pcibus_pnpinfo_str(device_t dev, device_t child, char *buf, 332186128Snwhitehorn size_t buflen) 333186128Snwhitehorn{ 334186128Snwhitehorn 335190113Smarius pci_child_pnpinfo_str_method(dev, child, buf, buflen); 336186128Snwhitehorn if (ofw_bus_get_node(child) != -1) { 337190113Smarius strlcat(buf, " ", buflen); /* Separate info. */ 338190113Smarius ofw_bus_gen_child_pnpinfo_str(dev, child, buf, buflen); 339186128Snwhitehorn } 340186128Snwhitehorn 341186128Snwhitehorn return (0); 342186128Snwhitehorn} 343