ofw_pci.c revision 117119
1/* 2 * Copyright (c) 1999, 2000 Matthew R. Green 3 * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * from: NetBSD: psycho.c,v 1.35 2001/09/10 16:17:06 eeh Exp 30 * 31 * $FreeBSD: head/sys/sparc64/pci/ofw_pci.c 117119 2003-07-01 14:52:47Z tmm $ 32 */ 33 34#include "opt_ofw_pci.h" 35 36#include <sys/param.h> 37#include <sys/kernel.h> 38#include <sys/systm.h> 39#include <sys/bus.h> 40 41#include <dev/pci/pcireg.h> 42#include <dev/pci/pcivar.h> 43 44#include <dev/ofw/ofw_pci.h> 45#include <dev/ofw/openfirm.h> 46 47#include <machine/bus.h> 48#include <machine/cache.h> 49#include <machine/iommureg.h> 50#include <machine/ofw_bus.h> 51#include <machine/ver.h> 52 53#include <sparc64/pci/ofw_pci.h> 54 55#include "pcib_if.h" 56 57u_int8_t pci_bus_cnt; 58phandle_t *pci_bus_map; 59int pci_bus_map_sz; 60 61#define PCI_BUS_MAP_INC 10 62 63#ifndef OFW_NEWPCI 64/* Do not swizzle on a PCI bus node with no interrupt-map propery. */ 65#define OPQ_NO_SWIZZLE 1 66/* 67 * INOs < 255 are really intpin numbers; use a driver method to figure out 68 * the real INO. 69 */ 70#define OPQ_INO_CALLBACK 2 71/* 72 * Do not map EBus interrupts at PCI buses, but assume that they are fully 73 * specified already. 74 */ 75#define OPQ_EBUS_NOMAP 4 76 77static struct ofw_pci_quirk { 78 char *opq_model; 79 int opq_quirks; 80} ofw_pci_quirks[] = { 81 { "SUNW,Ultra-4", OPQ_INO_CALLBACK | OPQ_EBUS_NOMAP }, 82 { "SUNW,Ultra-1-Engine", OPQ_NO_SWIZZLE }, 83}; 84#define OPQ_NENT (sizeof(ofw_pci_quirks) / sizeof(ofw_pci_quirks[0])) 85 86static int pci_quirks; 87 88#define OFW_PCI_PCIBUS "pci" 89#define OFW_PCI_EBUS "ebus" 90 91int 92ofw_pci_orb_callback(phandle_t node, u_int8_t *pintptr, int pintsz, 93 u_int8_t *pregptr, int pregsz, u_int8_t **rintr, int *terminate, 94 void *cookie) 95{ 96 device_t dev = cookie; 97 struct ofw_pci_register preg; 98 ofw_pci_intr_t pintr, intr; 99 u_int slot; 100 char type[32]; 101 int found = 0; 102 103 if ((pci_quirks & OPQ_EBUS_NOMAP) != 0 && 104 OF_getprop(node, "name", type, sizeof(type)) != -1 && 105 strcmp(type, OFW_PCI_EBUS) == 0) { 106 *terminate = 1; 107 return (-1); 108 } 109 if (pintsz != sizeof(pintr) || pregsz < sizeof(preg)) 110 return (-1); 111 bcopy(pintptr, &pintr, sizeof(pintr)); 112 bcopy(pregptr, &preg, sizeof(preg)); 113 slot = OFW_PCI_PHYS_HI_DEVICE(preg.phys_hi); 114 115 if ((pci_quirks & OPQ_INO_CALLBACK) != 0 && pintr <= 255) { 116 /* 117 * The e450 has no interrupt maps at all, and it usually has 118 * full interrupt numbers, including IGN, in the interrupt 119 * properties. There is one exception, however: the property 120 * values for external PCI devices seem to always be below 255 121 * and describe the interrupt pin to be used on the slot, while 122 * we have to figure out the base INO by looking at the slot 123 * number (which we do using an ofw_pci method). 124 * 125 * Of course, there is an exception to that nice rule: 126 * in the ebus case, the interrupt property has the correct 127 * INO (but without IGN). This is dealt with above. 128 */ 129 intr = OFW_PCI_GUESS_INO(dev, node, slot, pintr); 130 found = intr != 255; 131 *terminate = found; 132 } 133 if (!found && (pci_quirks & OPQ_NO_SWIZZLE) == 0 && 134 OF_getprop(node, "device_type", type, sizeof(type)) != -1 && 135 strcmp(type, OFW_PCI_PCIBUS) == 0 && pintr >= 1 && pintr <= 4) { 136 /* 137 * Handle a quirk found on some Netra t1 models: there exist 138 * PCI bridges without interrupt maps, where we apparently must 139 * do the PCI swizzle and continue to map on at the parent. 140 */ 141 intr = (slot + pintr + 3) % 4 + 1; 142 *terminate = 0; 143 found = 1; 144 } 145 146 if (found) { 147 *rintr = malloc(sizeof(intr), M_OFWPROP, M_WAITOK); 148 bcopy(&intr, *rintr, sizeof(intr)); 149 return (sizeof(intr)); 150 } else 151 return (-1); 152} 153 154static ofw_pci_intr_t 155ofw_pci_route_intr(device_t dev, phandle_t node, ofw_pci_intr_t ign) 156{ 157 u_int32_t rv; 158 159 rv = ofw_bus_route_intr(node, ORIP_NOINT, ofw_pci_orb_callback, dev); 160 if (rv == ORIR_NOTFOUND) 161 return (PCI_INVALID_IRQ); 162 /* 163 * Some machines (notably the SPARCengine Ultra AX and the e450) have 164 * no mappings at all, but use complete interrupt vector number 165 * including the IGN. Catch this case and remove the IGN. 166 */ 167 if (rv > ign) 168 rv -= ign; 169 return (rv); 170} 171#endif /* !OFW_NEWCPI */ 172 173u_int8_t 174ofw_pci_alloc_busno(phandle_t node) 175{ 176 phandle_t *om; 177 int osz; 178 u_int8_t n; 179 180 n = pci_bus_cnt++; 181 /* Establish a mapping between bus numbers and device nodes. */ 182 if (n >= pci_bus_map_sz) { 183 osz = pci_bus_map_sz; 184 om = pci_bus_map; 185 pci_bus_map_sz = n + PCI_BUS_MAP_INC; 186 pci_bus_map = malloc(sizeof(*pci_bus_map) * pci_bus_map_sz, 187 M_DEVBUF, M_WAITOK | M_ZERO); 188 if (om != NULL) { 189 bcopy(om, pci_bus_map, sizeof(*om) * osz); 190 free(om, M_DEVBUF); 191 } 192 } 193 pci_bus_map[n] = node; 194 return (n); 195} 196 197#ifndef OFW_NEWPCI 198/* 199 * Initialize bridge bus numbers for bridges that implement the primary, 200 * secondary and subordinate bus number registers. 201 */ 202void 203ofw_pci_binit(device_t busdev, struct ofw_pci_bdesc *obd) 204{ 205 206#ifdef OFW_PCI_DEBUG 207 printf("PCI-PCI bridge at %u/%u/%u: setting bus #s to %u/%u/%u\n", 208 obd->obd_bus, obd->obd_slot, obd->obd_func, obd->obd_bus, 209 obd->obd_secbus, obd->obd_subbus); 210#endif /* OFW_PCI_DEBUG */ 211 PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func, 212 PCIR_PRIBUS_1, obd->obd_bus, 1); 213 PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func, 214 PCIR_SECBUS_1, obd->obd_secbus, 1); 215 PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func, 216 PCIR_SUBBUS_1, obd->obd_subbus, 1); 217} 218 219/* 220 * Walk the PCI bus hierarchy, starting with the root PCI bus and descending 221 * through bridges, and initialize the interrupt line and latency timer 222 * configuration registers of attached devices using firmware information, 223 * as well as the the bus numbers and ranges of the bridges. 224 */ 225void 226ofw_pci_init(device_t dev, phandle_t bushdl, ofw_pci_intr_t ign, 227 struct ofw_pci_bdesc *obd) 228{ 229 struct ofw_pci_register pcir; 230 struct ofw_pci_bdesc subobd, *tobd; 231 phandle_t node; 232 char type[32]; 233 int i, intr, freemap; 234 u_int slot, busno, func, sub, lat; 235 u_int8_t clnsz; 236 237 /* Initialize the quirk list. */ 238 for (i = 0; i < OPQ_NENT; i++) { 239 if (strcmp(sparc64_model, ofw_pci_quirks[i].opq_model) == 0) { 240 pci_quirks = ofw_pci_quirks[i].opq_quirks; 241 break; 242 } 243 } 244 245 if ((node = OF_child(bushdl)) == 0) 246 return; 247 freemap = 0; 248 busno = obd->obd_secbus; 249 /* 250 * Compute the value to write into the cache line size register. 251 * The role of the streaming cache is unclear in write invalidate 252 * transfers, so it is made sure that it's line size is always reached. 253 */ 254 clnsz = imax(cache.ec_linesize, STRBUF_LINESZ); 255 KASSERT((clnsz / STRBUF_LINESZ) * STRBUF_LINESZ == clnsz && 256 (clnsz / cache.ec_linesize) * cache.ec_linesize == clnsz && 257 (clnsz / 4) * 4 == clnsz, ("bogus cache line size %d", clnsz)); 258 259 do { 260 if (node == -1) 261 panic("ofw_pci_init_intr: OF_child failed"); 262 if (OF_getprop(node, "device_type", type, sizeof(type)) == -1) 263 type[0] = '\0'; 264 else 265 type[sizeof(type) - 1] = '\0'; 266 if (OF_getprop(node, "reg", &pcir, sizeof(pcir)) == -1) 267 panic("ofw_pci_init: OF_getprop failed"); 268 slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi); 269 func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi); 270 PCIB_WRITE_CONFIG(dev, busno, slot, func, PCIR_CACHELNSZ, 271 clnsz / 4, 1); 272 if (strcmp(type, OFW_PCI_PCIBUS) == 0) { 273 /* 274 * This is a pci-pci bridge, initalize the bus number and 275 * recurse to initialize the child bus. The hierarchy is 276 * usually at most 2 levels deep, so recursion is 277 * feasible. 278 */ 279 subobd.obd_bus = busno; 280 subobd.obd_slot = slot; 281 subobd.obd_func = func; 282 sub = ofw_pci_alloc_busno(node); 283 subobd.obd_secbus = subobd.obd_subbus = sub; 284 /* Assume this bridge is mostly standard conforming. */ 285 subobd.obd_init = ofw_pci_binit; 286 subobd.obd_super = obd; 287 /* 288 * Need to change all subordinate bus registers of the 289 * bridges above this one now so that configuration 290 * transactions will get through. 291 */ 292 for (tobd = obd; tobd != NULL; tobd = tobd->obd_super) { 293 tobd->obd_subbus = sub; 294 tobd->obd_init(dev, tobd); 295 } 296 subobd.obd_init(dev, &subobd); 297#ifdef OFW_PCI_DEBUG 298 device_printf(dev, "%s: descending to " 299 "subordinate PCI bus\n", __func__); 300#endif /* OFW_PCI_DEBUG */ 301 ofw_pci_init(dev, node, ign, &subobd); 302 } else { 303 /* 304 * Initialize the latency timer register for 305 * busmaster devices to work properly. This is another 306 * task which the firmware does not always perform. 307 * The Min_Gnt register can be used to compute it's 308 * recommended value: it contains the desired latency 309 * in units of 1/4 us. To calculate the correct latency 310 * timer value, a bus clock of 33 and no wait states 311 * should be assumed. 312 */ 313 lat = PCIB_READ_CONFIG(dev, busno, slot, func, 314 PCIR_MINGNT, 1) * 33 / 4; 315 if (lat != 0) { 316#ifdef OFW_PCI_DEBUG 317 printf("device %d/%d/%d: latency timer %d -> " 318 "%d\n", busno, slot, func, 319 PCIB_READ_CONFIG(dev, busno, slot, func, 320 PCIR_LATTIMER, 1), lat); 321#endif /* OFW_PCI_DEBUG */ 322 PCIB_WRITE_CONFIG(dev, busno, slot, func, 323 PCIR_LATTIMER, imin(lat, 255), 1); 324 } 325 326 /* Initialize the intline registers. */ 327 if ((intr = ofw_pci_route_intr(dev, node, ign)) != 328 PCI_INVALID_IRQ) { 329#ifdef OFW_PCI_DEBUG 330 device_printf(dev, "%s: mapping intr for " 331 "%d/%d/%d to %d (preset was %d)\n", 332 __func__, busno, slot, func, intr, 333 (int)PCIB_READ_CONFIG(dev, busno, slot, 334 func, PCIR_INTLINE, 1)); 335#endif /* OFW_PCI_DEBUG */ 336 PCIB_WRITE_CONFIG(dev, busno, slot, func, 337 PCIR_INTLINE, intr, 1); 338 } else { 339#ifdef OFW_PCI_DEBUG 340 device_printf(dev, "%s: no interrupt " 341 "mapping found for %d/%d/%d (preset %d)\n", 342 __func__, busno, slot, func, 343 (int)PCIB_READ_CONFIG(dev, busno, slot, 344 func, PCIR_INTLINE, 1)); 345#endif /* OFW_PCI_DEBUG */ 346 /* 347 * The firmware initializes to 0 instead of 348 * 255. 349 */ 350 PCIB_WRITE_CONFIG(dev, busno, slot, func, 351 PCIR_INTLINE, PCI_INVALID_IRQ, 1); 352 } 353 } 354 } while ((node = OF_peer(node)) != 0); 355} 356 357phandle_t 358ofw_pci_find_node(int bus, int slot, int func) 359{ 360 phandle_t node, bnode; 361 struct ofw_pci_register pcir; 362 363 /* 364 * Retrieve the bus node from the mapping that was created on 365 * initialization. The bus numbers the firmware uses cannot be trusted, 366 * so they might have needed to be changed and this is necessary. 367 */ 368 if (bus >= pci_bus_map_sz) 369 return (0); 370 bnode = pci_bus_map[bus]; 371 if (bnode == 0) 372 return (0); 373 for (node = OF_child(bnode); node != 0 && node != -1; 374 node = OF_peer(node)) { 375 if (OF_getprop(node, "reg", &pcir, sizeof(pcir)) == -1) 376 continue; 377 if (OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi) == slot && 378 OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi) == func) 379 return (node); 380 } 381 return (0); 382} 383 384phandle_t 385ofw_pci_node(device_t dev) 386{ 387 388 return (ofw_pci_find_node(pci_get_bus(dev), pci_get_slot(dev), 389 pci_get_function(dev))); 390} 391#endif /* OFW_NEWPCI */ 392