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