xlp_pci.c revision 298029
1144518Sdavidxu/*- 2144518Sdavidxu * Copyright (c) 2003-2012 Broadcom Corporation 3144518Sdavidxu * All Rights Reserved 4144518Sdavidxu * 5144518Sdavidxu * Redistribution and use in source and binary forms, with or without 6144518Sdavidxu * modification, are permitted provided that the following conditions 7144518Sdavidxu * are met: 8144518Sdavidxu * 9144518Sdavidxu * 1. Redistributions of source code must retain the above copyright 10144518Sdavidxu * notice, this list of conditions and the following disclaimer. 11144518Sdavidxu * 2. Redistributions in binary form must reproduce the above copyright 12144518Sdavidxu * notice, this list of conditions and the following disclaimer in 13144518Sdavidxu * the documentation and/or other materials provided with the 14144518Sdavidxu * distribution. 15144518Sdavidxu * 16144518Sdavidxu * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR 17144518Sdavidxu * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18144518Sdavidxu * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19144518Sdavidxu * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE 20144518Sdavidxu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21144518Sdavidxu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22144518Sdavidxu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23144518Sdavidxu * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24144518Sdavidxu * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25144518Sdavidxu * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26144518Sdavidxu * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27144518Sdavidxu */ 28144518Sdavidxu 29144518Sdavidxu#include <sys/cdefs.h> 30144518Sdavidxu__FBSDID("$FreeBSD: head/sys/mips/nlm/xlp_pci.c 298029 2016-04-15 03:42:12Z jhb $"); 31144518Sdavidxu 32162061Sdavidxu#include <sys/param.h> 33144518Sdavidxu#include <sys/systm.h> 34144518Sdavidxu#include <sys/types.h> 35212077Sdavidxu#include <sys/kernel.h> 36212077Sdavidxu#include <sys/module.h> 37162061Sdavidxu#include <sys/malloc.h> 38233912Sdavidxu#include <sys/bus.h> 39179970Sdavidxu#include <sys/endian.h> 40216641Sdavidxu#include <sys/rman.h> 41179970Sdavidxu#include <sys/pciio.h> 42161680Sdavidxu 43179970Sdavidxu#include <vm/vm.h> 44163334Sdavidxu#include <vm/vm_param.h> 45161680Sdavidxu#include <vm/pmap.h> 46161680Sdavidxu 47161680Sdavidxu#include <dev/pci/pcivar.h> 48163334Sdavidxu#include <dev/pci/pcireg.h> 49212077Sdavidxu#include <dev/pci/pci_private.h> 50212077Sdavidxu 51173801Sdavidxu#include <dev/uart/uart.h> 52162061Sdavidxu#include <dev/uart/uart_bus.h> 53173801Sdavidxu#include <dev/uart/uart_cpu.h> 54178647Sdavidxu 55216641Sdavidxu#include <dev/ofw/openfirm.h> 56216641Sdavidxu#include <dev/ofw/ofw_bus.h> 57178647Sdavidxu#include <dev/ofw/ofw_bus_subr.h> 58164877Sdavidxu 59249985Sjilles#include <machine/bus.h> 60164902Sdavidxu#include <machine/md_var.h> 61164902Sdavidxu#include <machine/intr_machdep.h> 62164902Sdavidxu#include <machine/cpuregs.h> 63162061Sdavidxu 64232209Sdavidxu#include <mips/nlm/hal/haldefs.h> 65232209Sdavidxu#include <mips/nlm/interrupt.h> 66232209Sdavidxu#include <mips/nlm/hal/iomap.h> 67232209Sdavidxu#include <mips/nlm/hal/mips-extns.h> 68177850Sdavidxu#include <mips/nlm/hal/pic.h> 69177850Sdavidxu#include <mips/nlm/hal/bridge.h> 70212076Sdavidxu#include <mips/nlm/hal/gbu.h> 71212076Sdavidxu#include <mips/nlm/hal/pcibus.h> 72212076Sdavidxu#include <mips/nlm/hal/uart.h> 73212076Sdavidxu#include <mips/nlm/xlp.h> 74212076Sdavidxu 75144518Sdavidxu#include "pcib_if.h" 76161680Sdavidxu#include "pci_if.h" 77161680Sdavidxu 78161680Sdavidxustatic int 79161680Sdavidxuxlp_pci_attach(device_t dev) 80161680Sdavidxu{ 81161680Sdavidxu struct pci_devinfo *dinfo; 82163334Sdavidxu device_t pcib; 83161680Sdavidxu int maxslots, s, f, pcifunchigh, irq; 84161680Sdavidxu int busno, node, devoffset; 85161680Sdavidxu uint16_t devid; 86165206Sdavidxu uint8_t hdrtype; 87165206Sdavidxu 88179970Sdavidxu /* 89165206Sdavidxu * The on-chip devices are on a bus that is almost, but not 90179970Sdavidxu * quite, completely like PCI. Add those things by hand. 91179970Sdavidxu */ 92179970Sdavidxu pcib = device_get_parent(dev); 93179970Sdavidxu busno = pcib_get_bus(dev); 94165206Sdavidxu maxslots = PCIB_MAXSLOTS(pcib); 95165206Sdavidxu for (s = 0; s <= maxslots; s++) { 96165206Sdavidxu pcifunchigh = 0; 97165206Sdavidxu f = 0; 98161680Sdavidxu hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1); 99161680Sdavidxu if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) 100179970Sdavidxu continue; 101161680Sdavidxu if (hdrtype & PCIM_MFDEV) 102179970Sdavidxu pcifunchigh = PCI_FUNCMAX; 103161680Sdavidxu node = s / 8; 104161680Sdavidxu for (f = 0; f <= pcifunchigh; f++) { 105161680Sdavidxu devoffset = XLP_HDR_OFFSET(node, 0, s % 8, f); 106216641Sdavidxu if (!nlm_dev_exists(devoffset)) 107216641Sdavidxu continue; 108216641Sdavidxu 109216641Sdavidxu /* Find if there is a desc for the SoC device */ 110216641Sdavidxu devid = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_DEVICE, 2); 111216641Sdavidxu 112216641Sdavidxu /* Skip devices that don't have a proper PCI header */ 113216641Sdavidxu switch (devid) { 114161680Sdavidxu case PCI_DEVICE_ID_NLM_ICI: 115161680Sdavidxu case PCI_DEVICE_ID_NLM_PIC: 116161680Sdavidxu case PCI_DEVICE_ID_NLM_FMN: 117179970Sdavidxu case PCI_DEVICE_ID_NLM_UART: 118161680Sdavidxu case PCI_DEVICE_ID_NLM_I2C: 119179970Sdavidxu case PCI_DEVICE_ID_NLM_NOR: 120161680Sdavidxu case PCI_DEVICE_ID_NLM_MMC: 121161680Sdavidxu continue; 122161680Sdavidxu case PCI_DEVICE_ID_NLM_EHCI: 123239200Sdavidxu irq = PIC_USB_IRQ(f); 124161680Sdavidxu PCIB_WRITE_CONFIG(pcib, busno, s, f, 125233912Sdavidxu XLP_PCI_DEVSCRATCH_REG0 << 2, 126233912Sdavidxu (1 << 8) | irq, 4); 127233912Sdavidxu } 128233912Sdavidxu dinfo = pci_read_device(pcib, dev, pcib_get_domain(dev), 129233912Sdavidxu busno, s, f); 130233912Sdavidxu pci_add_child(dev, dinfo); 131233912Sdavidxu } 132233912Sdavidxu } 133233912Sdavidxu return (bus_generic_attach(dev)); 134233912Sdavidxu} 135239200Sdavidxu 136239200Sdavidxustatic int 137239200Sdavidxuxlp_pci_probe(device_t dev) 138239200Sdavidxu{ 139239200Sdavidxu device_t pcib; 140239200Sdavidxu 141233912Sdavidxu pcib = device_get_parent(dev); 142233912Sdavidxu /* 143233912Sdavidxu * Only the top level bus has SoC devices, leave the rest to 144233912Sdavidxu * Generic PCI code 145233912Sdavidxu */ 146161680Sdavidxu if (strcmp(device_get_nameunit(pcib), "pcib0") != 0) 147161680Sdavidxu return (ENXIO); 148177850Sdavidxu device_set_desc(dev, "XLP SoCbus"); 149239200Sdavidxu return (BUS_PROBE_DEFAULT); 150239200Sdavidxu} 151239200Sdavidxu 152239200Sdavidxustatic devclass_t pci_devclass; 153239200Sdavidxustatic device_method_t xlp_pci_methods[] = { 154239200Sdavidxu /* Device interface */ 155177850Sdavidxu DEVMETHOD(device_probe, xlp_pci_probe), 156177850Sdavidxu DEVMETHOD(device_attach, xlp_pci_attach), 157177850Sdavidxu DEVMETHOD_END 158177850Sdavidxu}; 159177850Sdavidxu 160177850SdavidxuDEFINE_CLASS_1(pci, xlp_pci_driver, xlp_pci_methods, sizeof(struct pci_softc), 161177850Sdavidxu pci_driver); 162177850SdavidxuDRIVER_MODULE(xlp_pci, pcib, xlp_pci_driver, pci_devclass, 0, 0); 163177850Sdavidxu 164177850Sdavidxustatic int 165177850Sdavidxuxlp_pcib_probe(device_t dev) 166177850Sdavidxu{ 167177850Sdavidxu 168177850Sdavidxu if (ofw_bus_is_compatible(dev, "netlogic,xlp-pci")) { 169177850Sdavidxu device_set_desc(dev, "XLP PCI bus"); 170177850Sdavidxu return (BUS_PROBE_DEFAULT); 171177850Sdavidxu } 172177850Sdavidxu return (ENXIO); 173177850Sdavidxu} 174177850Sdavidxu 175177850Sdavidxustatic int 176177850Sdavidxuxlp_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 177177850Sdavidxu{ 178177850Sdavidxu 179177850Sdavidxu switch (which) { 180177850Sdavidxu case PCIB_IVAR_DOMAIN: 181177850Sdavidxu *result = 0; 182177850Sdavidxu return (0); 183177850Sdavidxu case PCIB_IVAR_BUS: 184177850Sdavidxu *result = 0; 185177850Sdavidxu return (0); 186177850Sdavidxu } 187177850Sdavidxu return (ENOENT); 188177850Sdavidxu} 189177850Sdavidxu 190177850Sdavidxustatic int 191177850Sdavidxuxlp_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t result) 192177850Sdavidxu{ 193177850Sdavidxu switch (which) { 194177850Sdavidxu case PCIB_IVAR_DOMAIN: 195177850Sdavidxu return (EINVAL); 196177850Sdavidxu case PCIB_IVAR_BUS: 197177850Sdavidxu return (EINVAL); 198177850Sdavidxu } 199177850Sdavidxu return (ENOENT); 200177850Sdavidxu} 201177850Sdavidxu 202177850Sdavidxustatic int 203177850Sdavidxuxlp_pcib_maxslots(device_t dev) 204177850Sdavidxu{ 205177850Sdavidxu 206177850Sdavidxu return (PCI_SLOTMAX); 207177850Sdavidxu} 208177850Sdavidxu 209177850Sdavidxustatic u_int32_t 210177850Sdavidxuxlp_pcib_read_config(device_t dev, u_int b, u_int s, u_int f, 211177850Sdavidxu u_int reg, int width) 212177850Sdavidxu{ 213177850Sdavidxu uint32_t data = 0; 214177850Sdavidxu uint64_t cfgaddr; 215177850Sdavidxu int regindex = reg/sizeof(uint32_t); 216177850Sdavidxu 217177850Sdavidxu cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f)); 218177850Sdavidxu if ((width == 2) && (reg & 1)) 219177850Sdavidxu return 0xFFFFFFFF; 220197445Sattilio else if ((width == 4) && (reg & 3)) 221197445Sattilio return 0xFFFFFFFF; 222197445Sattilio 223197445Sattilio /* 224197445Sattilio * The intline and int pin of SoC devices are DOA, except 225177850Sdavidxu * for bridges (slot %8 == 1). 226177850Sdavidxu * use the values we stashed in a writable PCI scratch reg. 227177850Sdavidxu */ 228177850Sdavidxu if (b == 0 && regindex == 0xf && s % 8 > 1) 229177850Sdavidxu regindex = XLP_PCI_DEVSCRATCH_REG0; 230177850Sdavidxu 231177850Sdavidxu data = nlm_read_pci_reg(cfgaddr, regindex); 232177850Sdavidxu if (width == 1) 233177850Sdavidxu return ((data >> ((reg & 3) << 3)) & 0xff); 234144518Sdavidxu else if (width == 2) 235 return ((data >> ((reg & 3) << 3)) & 0xffff); 236 else 237 return (data); 238} 239 240static void 241xlp_pcib_write_config(device_t dev, u_int b, u_int s, u_int f, 242 u_int reg, u_int32_t val, int width) 243{ 244 uint64_t cfgaddr; 245 uint32_t data = 0; 246 int regindex = reg / sizeof(uint32_t); 247 248 cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f)); 249 if ((width == 2) && (reg & 1)) 250 return; 251 else if ((width == 4) && (reg & 3)) 252 return; 253 254 if (width == 1) { 255 data = nlm_read_pci_reg(cfgaddr, regindex); 256 data = (data & ~(0xff << ((reg & 3) << 3))) | 257 (val << ((reg & 3) << 3)); 258 } else if (width == 2) { 259 data = nlm_read_pci_reg(cfgaddr, regindex); 260 data = (data & ~(0xffff << ((reg & 3) << 3))) | 261 (val << ((reg & 3) << 3)); 262 } else { 263 data = val; 264 } 265 266 /* 267 * use shadow reg for intpin/intline which are dead 268 */ 269 if (b == 0 && regindex == 0xf && s % 8 > 1) 270 regindex = XLP_PCI_DEVSCRATCH_REG0; 271 nlm_write_pci_reg(cfgaddr, regindex, data); 272} 273 274/* 275 * Enable byte swap in hardware when compiled big-endian. 276 * Programs a link's PCIe SWAP regions from the link's IO and MEM address 277 * ranges. 278 */ 279static void 280xlp_pcib_hardware_swap_enable(int node, int link) 281{ 282#if BYTE_ORDER == BIG_ENDIAN 283 uint64_t bbase, linkpcibase; 284 uint32_t bar; 285 int pcieoffset; 286 287 pcieoffset = XLP_IO_PCIE_OFFSET(node, link); 288 if (!nlm_dev_exists(pcieoffset)) 289 return; 290 291 bbase = nlm_get_bridge_regbase(node); 292 linkpcibase = nlm_pcicfg_base(pcieoffset); 293 bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEMEM_BASE0 + link); 294 nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_MEM_BASE, bar); 295 296 bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEMEM_LIMIT0 + link); 297 nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_MEM_LIM, bar | 0xFFF); 298 299 bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEIO_BASE0 + link); 300 nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_BASE, bar); 301 302 bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEIO_LIMIT0 + link); 303 nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_LIM, bar | 0xFFF); 304#endif 305} 306 307static int 308xlp_pcib_attach(device_t dev) 309{ 310 int node, link; 311 312 /* enable hardware swap on all nodes/links */ 313 for (node = 0; node < XLP_MAX_NODES; node++) 314 for (link = 0; link < 4; link++) 315 xlp_pcib_hardware_swap_enable(node, link); 316 317 device_add_child(dev, "pci", -1); 318 bus_generic_attach(dev); 319 return (0); 320} 321 322/* 323 * XLS PCIe can have upto 4 links, and each link has its on IRQ 324 * Find the link on which the device is on 325 */ 326static int 327xlp_pcie_link(device_t pcib, device_t dev) 328{ 329 device_t parent, tmp; 330 331 /* find the lane on which the slot is connected to */ 332 tmp = dev; 333 while (1) { 334 parent = device_get_parent(tmp); 335 if (parent == NULL || parent == pcib) { 336 device_printf(dev, "Cannot find parent bus\n"); 337 return (-1); 338 } 339 if (strcmp(device_get_nameunit(parent), "pci0") == 0) 340 break; 341 tmp = parent; 342 } 343 return (pci_get_function(tmp)); 344} 345 346static int 347xlp_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs) 348{ 349 int i, link; 350 351 /* 352 * Each link has 32 MSIs that can be allocated, but for now 353 * we only support one device per link. 354 * msi_alloc() equivalent is needed when we start supporting 355 * bridges on the PCIe link. 356 */ 357 link = xlp_pcie_link(pcib, dev); 358 if (link == -1) 359 return (ENXIO); 360 361 /* 362 * encode the irq so that we know it is a MSI interrupt when we 363 * setup interrupts 364 */ 365 for (i = 0; i < count; i++) 366 irqs[i] = 64 + link * 32 + i; 367 368 return (0); 369} 370 371static int 372xlp_release_msi(device_t pcib, device_t dev, int count, int *irqs) 373{ 374 return (0); 375} 376 377static int 378xlp_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, 379 uint32_t *data) 380{ 381 int link; 382 383 if (irq < 64) { 384 device_printf(dev, "%s: map_msi for irq %d - ignored", 385 device_get_nameunit(pcib), irq); 386 return (ENXIO); 387 } 388 link = (irq - 64) / 32; 389 *addr = MIPS_MSI_ADDR(0); 390 *data = MIPS_MSI_DATA(PIC_PCIE_IRQ(link)); 391 return (0); 392} 393 394static void 395bridge_pcie_ack(int irq, void *arg) 396{ 397 uint32_t node,reg; 398 uint64_t base; 399 400 node = nlm_nodeid(); 401 reg = PCIE_MSI_STATUS; 402 403 switch (irq) { 404 case PIC_PCIE_0_IRQ: 405 base = nlm_pcicfg_base(XLP_IO_PCIE0_OFFSET(node)); 406 break; 407 case PIC_PCIE_1_IRQ: 408 base = nlm_pcicfg_base(XLP_IO_PCIE1_OFFSET(node)); 409 break; 410 case PIC_PCIE_2_IRQ: 411 base = nlm_pcicfg_base(XLP_IO_PCIE2_OFFSET(node)); 412 break; 413 case PIC_PCIE_3_IRQ: 414 base = nlm_pcicfg_base(XLP_IO_PCIE3_OFFSET(node)); 415 break; 416 default: 417 return; 418 } 419 420 nlm_write_pci_reg(base, reg, 0xFFFFFFFF); 421 return; 422} 423 424static int 425mips_platform_pcib_setup_intr(device_t dev, device_t child, 426 struct resource *irq, int flags, driver_filter_t *filt, 427 driver_intr_t *intr, void *arg, void **cookiep) 428{ 429 int error = 0; 430 int xlpirq; 431 432 error = rman_activate_resource(irq); 433 if (error) 434 return error; 435 if (rman_get_start(irq) != rman_get_end(irq)) { 436 device_printf(dev, "Interrupt allocation %ju != %ju\n", 437 rman_get_start(irq), rman_get_end(irq)); 438 return (EINVAL); 439 } 440 xlpirq = rman_get_start(irq); 441 if (xlpirq == 0) 442 return (0); 443 444 if (strcmp(device_get_name(dev), "pcib") != 0) 445 return (0); 446 447 /* 448 * temporary hack for MSI, we support just one device per 449 * link, and assign the link interrupt to the device interrupt 450 */ 451 if (xlpirq >= 64) { 452 int node, val, link; 453 uint64_t base; 454 455 xlpirq -= 64; 456 if (xlpirq % 32 != 0) 457 return (0); 458 459 node = nlm_nodeid(); 460 link = xlpirq / 32; 461 base = nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node,link)); 462 463 /* MSI Interrupt Vector enable at bridge's configuration */ 464 nlm_write_pci_reg(base, PCIE_MSI_EN, PCIE_MSI_VECTOR_INT_EN); 465 466 val = nlm_read_pci_reg(base, PCIE_INT_EN0); 467 /* MSI Interrupt enable at bridge's configuration */ 468 nlm_write_pci_reg(base, PCIE_INT_EN0, 469 (val | PCIE_MSI_INT_EN)); 470 471 /* legacy interrupt disable at bridge */ 472 val = nlm_read_pci_reg(base, PCIE_BRIDGE_CMD); 473 nlm_write_pci_reg(base, PCIE_BRIDGE_CMD, 474 (val | PCIM_CMD_INTxDIS)); 475 476 /* MSI address update at bridge */ 477 nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_ADDRL, 478 MSI_MIPS_ADDR_BASE); 479 nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_ADDRH, 0); 480 481 val = nlm_read_pci_reg(base, PCIE_BRIDGE_MSI_CAP); 482 /* MSI capability enable at bridge */ 483 nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_CAP, 484 (val | (PCIM_MSICTRL_MSI_ENABLE << 16) | 485 (PCIM_MSICTRL_MMC_32 << 16))); 486 xlpirq = PIC_PCIE_IRQ(link); 487 } 488 489 /* if it is for real PCIe, we need to ack at bridge too */ 490 if (xlpirq >= PIC_PCIE_IRQ(0) && xlpirq <= PIC_PCIE_IRQ(3)) 491 xlp_set_bus_ack(xlpirq, bridge_pcie_ack, NULL); 492 cpu_establish_hardintr(device_get_name(child), filt, intr, arg, 493 xlpirq, flags, cookiep); 494 495 return (0); 496} 497 498static int 499mips_platform_pcib_teardown_intr(device_t dev, device_t child, 500 struct resource *irq, void *cookie) 501{ 502 if (strcmp(device_get_name(child), "pci") == 0) { 503 /* if needed reprogram the pic to clear pcix related entry */ 504 device_printf(dev, "teardown intr\n"); 505 } 506 return (bus_generic_teardown_intr(dev, child, irq, cookie)); 507} 508 509static int 510mips_pcib_route_interrupt(device_t bus, device_t dev, int pin) 511{ 512 int f, d; 513 514 /* 515 * Validate requested pin number. 516 */ 517 if ((pin < 1) || (pin > 4)) 518 return (255); 519 520 if (pci_get_bus(dev) == 0 && 521 pci_get_vendor(dev) == PCI_VENDOR_NETLOGIC) { 522 f = pci_get_function(dev); 523 d = pci_get_slot(dev) % 8; 524 525 /* 526 * For PCIe links, return link IRT, for other SoC devices 527 * get the IRT from its PCIe header 528 */ 529 if (d == 1) 530 return (PIC_PCIE_IRQ(f)); 531 else 532 return (255); /* use intline, don't reroute */ 533 } else { 534 /* Regular PCI devices */ 535 return (PIC_PCIE_IRQ(xlp_pcie_link(bus, dev))); 536 } 537} 538 539static device_method_t xlp_pcib_methods[] = { 540 /* Device interface */ 541 DEVMETHOD(device_probe, xlp_pcib_probe), 542 DEVMETHOD(device_attach, xlp_pcib_attach), 543 544 /* Bus interface */ 545 DEVMETHOD(bus_read_ivar, xlp_pcib_read_ivar), 546 DEVMETHOD(bus_write_ivar, xlp_pcib_write_ivar), 547 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 548 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 549 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 550 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 551 DEVMETHOD(bus_setup_intr, mips_platform_pcib_setup_intr), 552 DEVMETHOD(bus_teardown_intr, mips_platform_pcib_teardown_intr), 553 554 /* pcib interface */ 555 DEVMETHOD(pcib_maxslots, xlp_pcib_maxslots), 556 DEVMETHOD(pcib_read_config, xlp_pcib_read_config), 557 DEVMETHOD(pcib_write_config, xlp_pcib_write_config), 558 DEVMETHOD(pcib_route_interrupt, mips_pcib_route_interrupt), 559 560 DEVMETHOD(pcib_alloc_msi, xlp_alloc_msi), 561 DEVMETHOD(pcib_release_msi, xlp_release_msi), 562 DEVMETHOD(pcib_map_msi, xlp_map_msi), 563 564 DEVMETHOD_END 565}; 566 567static driver_t xlp_pcib_driver = { 568 "pcib", 569 xlp_pcib_methods, 570 1, /* no softc */ 571}; 572 573static devclass_t pcib_devclass; 574DRIVER_MODULE(xlp_pcib, simplebus, xlp_pcib_driver, pcib_devclass, 0, 0); 575