xlp_pci.c revision 298712
1/*- 2 * Copyright (c) 2003-2012 Broadcom Corporation 3 * All Rights Reserved 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 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 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: head/sys/mips/nlm/xlp_pci.c 298712 2016-04-27 17:49:42Z jhb $"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/types.h> 35#include <sys/kernel.h> 36#include <sys/module.h> 37#include <sys/malloc.h> 38#include <sys/bus.h> 39#include <sys/endian.h> 40#include <sys/rman.h> 41#include <sys/pciio.h> 42 43#include <vm/vm.h> 44#include <vm/vm_param.h> 45#include <vm/pmap.h> 46 47#include <dev/pci/pcivar.h> 48#include <dev/pci/pcireg.h> 49#include <dev/pci/pci_private.h> 50 51#include <dev/uart/uart.h> 52#include <dev/uart/uart_bus.h> 53#include <dev/uart/uart_cpu.h> 54 55#include <dev/ofw/openfirm.h> 56#include <dev/ofw/ofw_bus.h> 57#include <dev/ofw/ofw_bus_subr.h> 58 59#include <machine/bus.h> 60#include <machine/md_var.h> 61#include <machine/intr_machdep.h> 62#include <machine/cpuregs.h> 63 64#include <mips/nlm/hal/haldefs.h> 65#include <mips/nlm/interrupt.h> 66#include <mips/nlm/hal/iomap.h> 67#include <mips/nlm/hal/mips-extns.h> 68#include <mips/nlm/hal/pic.h> 69#include <mips/nlm/hal/bridge.h> 70#include <mips/nlm/hal/gbu.h> 71#include <mips/nlm/hal/pcibus.h> 72#include <mips/nlm/hal/uart.h> 73#include <mips/nlm/xlp.h> 74 75#include "pcib_if.h" 76#include "pci_if.h" 77 78static int 79xlp_pci_attach(device_t dev) 80{ 81 struct pci_devinfo *dinfo; 82 device_t pcib; 83 int maxslots, s, f, pcifunchigh, irq; 84 int busno, node, devoffset; 85 uint16_t devid; 86 uint8_t hdrtype; 87 88 /* 89 * The on-chip devices are on a bus that is almost, but not 90 * quite, completely like PCI. Add those things by hand. 91 */ 92 pcib = device_get_parent(dev); 93 busno = pcib_get_bus(dev); 94 maxslots = PCIB_MAXSLOTS(pcib); 95 for (s = 0; s <= maxslots; s++) { 96 pcifunchigh = 0; 97 f = 0; 98 hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1); 99 if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) 100 continue; 101 if (hdrtype & PCIM_MFDEV) 102 pcifunchigh = PCI_FUNCMAX; 103 node = s / 8; 104 for (f = 0; f <= pcifunchigh; f++) { 105 devoffset = XLP_HDR_OFFSET(node, 0, s % 8, f); 106 if (!nlm_dev_exists(devoffset)) 107 continue; 108 109 /* Find if there is a desc for the SoC device */ 110 devid = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_DEVICE, 2); 111 112 /* Skip devices that don't have a proper PCI header */ 113 switch (devid) { 114 case PCI_DEVICE_ID_NLM_ICI: 115 case PCI_DEVICE_ID_NLM_PIC: 116 case PCI_DEVICE_ID_NLM_FMN: 117 case PCI_DEVICE_ID_NLM_UART: 118 case PCI_DEVICE_ID_NLM_I2C: 119 case PCI_DEVICE_ID_NLM_NOR: 120 case PCI_DEVICE_ID_NLM_MMC: 121 continue; 122 case PCI_DEVICE_ID_NLM_EHCI: 123 irq = PIC_USB_IRQ(f); 124 PCIB_WRITE_CONFIG(pcib, busno, s, f, 125 XLP_PCI_DEVSCRATCH_REG0 << 2, 126 (1 << 8) | irq, 4); 127 } 128 dinfo = pci_read_device(pcib, dev, pcib_get_domain(dev), 129 busno, s, f); 130 pci_add_child(dev, dinfo); 131 } 132 } 133 return (bus_generic_attach(dev)); 134} 135 136static int 137xlp_pci_probe(device_t dev) 138{ 139 device_t pcib; 140 141 pcib = device_get_parent(dev); 142 /* 143 * Only the top level bus has SoC devices, leave the rest to 144 * Generic PCI code 145 */ 146 if (strcmp(device_get_nameunit(pcib), "pcib0") != 0) 147 return (ENXIO); 148 device_set_desc(dev, "XLP SoCbus"); 149 return (BUS_PROBE_DEFAULT); 150} 151 152static devclass_t pci_devclass; 153static device_method_t xlp_pci_methods[] = { 154 /* Device interface */ 155 DEVMETHOD(device_probe, xlp_pci_probe), 156 DEVMETHOD(device_attach, xlp_pci_attach), 157 DEVMETHOD(bus_rescan, bus_null_rescan), 158 DEVMETHOD_END 159}; 160 161DEFINE_CLASS_1(pci, xlp_pci_driver, xlp_pci_methods, sizeof(struct pci_softc), 162 pci_driver); 163DRIVER_MODULE(xlp_pci, pcib, xlp_pci_driver, pci_devclass, 0, 0); 164 165static int 166xlp_pcib_probe(device_t dev) 167{ 168 169 if (ofw_bus_is_compatible(dev, "netlogic,xlp-pci")) { 170 device_set_desc(dev, "XLP PCI bus"); 171 return (BUS_PROBE_DEFAULT); 172 } 173 return (ENXIO); 174} 175 176static int 177xlp_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 178{ 179 180 switch (which) { 181 case PCIB_IVAR_DOMAIN: 182 *result = 0; 183 return (0); 184 case PCIB_IVAR_BUS: 185 *result = 0; 186 return (0); 187 } 188 return (ENOENT); 189} 190 191static int 192xlp_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t result) 193{ 194 switch (which) { 195 case PCIB_IVAR_DOMAIN: 196 return (EINVAL); 197 case PCIB_IVAR_BUS: 198 return (EINVAL); 199 } 200 return (ENOENT); 201} 202 203static int 204xlp_pcib_maxslots(device_t dev) 205{ 206 207 return (PCI_SLOTMAX); 208} 209 210static u_int32_t 211xlp_pcib_read_config(device_t dev, u_int b, u_int s, u_int f, 212 u_int reg, int width) 213{ 214 uint32_t data = 0; 215 uint64_t cfgaddr; 216 int regindex = reg/sizeof(uint32_t); 217 218 cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f)); 219 if ((width == 2) && (reg & 1)) 220 return 0xFFFFFFFF; 221 else if ((width == 4) && (reg & 3)) 222 return 0xFFFFFFFF; 223 224 /* 225 * The intline and int pin of SoC devices are DOA, except 226 * for bridges (slot %8 == 1). 227 * use the values we stashed in a writable PCI scratch reg. 228 */ 229 if (b == 0 && regindex == 0xf && s % 8 > 1) 230 regindex = XLP_PCI_DEVSCRATCH_REG0; 231 232 data = nlm_read_pci_reg(cfgaddr, regindex); 233 if (width == 1) 234 return ((data >> ((reg & 3) << 3)) & 0xff); 235 else if (width == 2) 236 return ((data >> ((reg & 3) << 3)) & 0xffff); 237 else 238 return (data); 239} 240 241static void 242xlp_pcib_write_config(device_t dev, u_int b, u_int s, u_int f, 243 u_int reg, u_int32_t val, int width) 244{ 245 uint64_t cfgaddr; 246 uint32_t data = 0; 247 int regindex = reg / sizeof(uint32_t); 248 249 cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f)); 250 if ((width == 2) && (reg & 1)) 251 return; 252 else if ((width == 4) && (reg & 3)) 253 return; 254 255 if (width == 1) { 256 data = nlm_read_pci_reg(cfgaddr, regindex); 257 data = (data & ~(0xff << ((reg & 3) << 3))) | 258 (val << ((reg & 3) << 3)); 259 } else if (width == 2) { 260 data = nlm_read_pci_reg(cfgaddr, regindex); 261 data = (data & ~(0xffff << ((reg & 3) << 3))) | 262 (val << ((reg & 3) << 3)); 263 } else { 264 data = val; 265 } 266 267 /* 268 * use shadow reg for intpin/intline which are dead 269 */ 270 if (b == 0 && regindex == 0xf && s % 8 > 1) 271 regindex = XLP_PCI_DEVSCRATCH_REG0; 272 nlm_write_pci_reg(cfgaddr, regindex, data); 273} 274 275/* 276 * Enable byte swap in hardware when compiled big-endian. 277 * Programs a link's PCIe SWAP regions from the link's IO and MEM address 278 * ranges. 279 */ 280static void 281xlp_pcib_hardware_swap_enable(int node, int link) 282{ 283#if BYTE_ORDER == BIG_ENDIAN 284 uint64_t bbase, linkpcibase; 285 uint32_t bar; 286 int pcieoffset; 287 288 pcieoffset = XLP_IO_PCIE_OFFSET(node, link); 289 if (!nlm_dev_exists(pcieoffset)) 290 return; 291 292 bbase = nlm_get_bridge_regbase(node); 293 linkpcibase = nlm_pcicfg_base(pcieoffset); 294 bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEMEM_BASE0 + link); 295 nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_MEM_BASE, bar); 296 297 bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEMEM_LIMIT0 + link); 298 nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_MEM_LIM, bar | 0xFFF); 299 300 bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEIO_BASE0 + link); 301 nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_BASE, bar); 302 303 bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEIO_LIMIT0 + link); 304 nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_LIM, bar | 0xFFF); 305#endif 306} 307 308static int 309xlp_pcib_attach(device_t dev) 310{ 311 int node, link; 312 313 /* enable hardware swap on all nodes/links */ 314 for (node = 0; node < XLP_MAX_NODES; node++) 315 for (link = 0; link < 4; link++) 316 xlp_pcib_hardware_swap_enable(node, link); 317 318 device_add_child(dev, "pci", -1); 319 bus_generic_attach(dev); 320 return (0); 321} 322 323/* 324 * XLS PCIe can have upto 4 links, and each link has its on IRQ 325 * Find the link on which the device is on 326 */ 327static int 328xlp_pcie_link(device_t pcib, device_t dev) 329{ 330 device_t parent, tmp; 331 332 /* find the lane on which the slot is connected to */ 333 tmp = dev; 334 while (1) { 335 parent = device_get_parent(tmp); 336 if (parent == NULL || parent == pcib) { 337 device_printf(dev, "Cannot find parent bus\n"); 338 return (-1); 339 } 340 if (strcmp(device_get_nameunit(parent), "pci0") == 0) 341 break; 342 tmp = parent; 343 } 344 return (pci_get_function(tmp)); 345} 346 347static int 348xlp_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs) 349{ 350 int i, link; 351 352 /* 353 * Each link has 32 MSIs that can be allocated, but for now 354 * we only support one device per link. 355 * msi_alloc() equivalent is needed when we start supporting 356 * bridges on the PCIe link. 357 */ 358 link = xlp_pcie_link(pcib, dev); 359 if (link == -1) 360 return (ENXIO); 361 362 /* 363 * encode the irq so that we know it is a MSI interrupt when we 364 * setup interrupts 365 */ 366 for (i = 0; i < count; i++) 367 irqs[i] = 64 + link * 32 + i; 368 369 return (0); 370} 371 372static int 373xlp_release_msi(device_t pcib, device_t dev, int count, int *irqs) 374{ 375 return (0); 376} 377 378static int 379xlp_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, 380 uint32_t *data) 381{ 382 int link; 383 384 if (irq < 64) { 385 device_printf(dev, "%s: map_msi for irq %d - ignored", 386 device_get_nameunit(pcib), irq); 387 return (ENXIO); 388 } 389 link = (irq - 64) / 32; 390 *addr = MIPS_MSI_ADDR(0); 391 *data = MIPS_MSI_DATA(PIC_PCIE_IRQ(link)); 392 return (0); 393} 394 395static void 396bridge_pcie_ack(int irq, void *arg) 397{ 398 uint32_t node,reg; 399 uint64_t base; 400 401 node = nlm_nodeid(); 402 reg = PCIE_MSI_STATUS; 403 404 switch (irq) { 405 case PIC_PCIE_0_IRQ: 406 base = nlm_pcicfg_base(XLP_IO_PCIE0_OFFSET(node)); 407 break; 408 case PIC_PCIE_1_IRQ: 409 base = nlm_pcicfg_base(XLP_IO_PCIE1_OFFSET(node)); 410 break; 411 case PIC_PCIE_2_IRQ: 412 base = nlm_pcicfg_base(XLP_IO_PCIE2_OFFSET(node)); 413 break; 414 case PIC_PCIE_3_IRQ: 415 base = nlm_pcicfg_base(XLP_IO_PCIE3_OFFSET(node)); 416 break; 417 default: 418 return; 419 } 420 421 nlm_write_pci_reg(base, reg, 0xFFFFFFFF); 422 return; 423} 424 425static int 426mips_platform_pcib_setup_intr(device_t dev, device_t child, 427 struct resource *irq, int flags, driver_filter_t *filt, 428 driver_intr_t *intr, void *arg, void **cookiep) 429{ 430 int error = 0; 431 int xlpirq; 432 433 error = rman_activate_resource(irq); 434 if (error) 435 return error; 436 if (rman_get_start(irq) != rman_get_end(irq)) { 437 device_printf(dev, "Interrupt allocation %ju != %ju\n", 438 rman_get_start(irq), rman_get_end(irq)); 439 return (EINVAL); 440 } 441 xlpirq = rman_get_start(irq); 442 if (xlpirq == 0) 443 return (0); 444 445 if (strcmp(device_get_name(dev), "pcib") != 0) 446 return (0); 447 448 /* 449 * temporary hack for MSI, we support just one device per 450 * link, and assign the link interrupt to the device interrupt 451 */ 452 if (xlpirq >= 64) { 453 int node, val, link; 454 uint64_t base; 455 456 xlpirq -= 64; 457 if (xlpirq % 32 != 0) 458 return (0); 459 460 node = nlm_nodeid(); 461 link = xlpirq / 32; 462 base = nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node,link)); 463 464 /* MSI Interrupt Vector enable at bridge's configuration */ 465 nlm_write_pci_reg(base, PCIE_MSI_EN, PCIE_MSI_VECTOR_INT_EN); 466 467 val = nlm_read_pci_reg(base, PCIE_INT_EN0); 468 /* MSI Interrupt enable at bridge's configuration */ 469 nlm_write_pci_reg(base, PCIE_INT_EN0, 470 (val | PCIE_MSI_INT_EN)); 471 472 /* legacy interrupt disable at bridge */ 473 val = nlm_read_pci_reg(base, PCIE_BRIDGE_CMD); 474 nlm_write_pci_reg(base, PCIE_BRIDGE_CMD, 475 (val | PCIM_CMD_INTxDIS)); 476 477 /* MSI address update at bridge */ 478 nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_ADDRL, 479 MSI_MIPS_ADDR_BASE); 480 nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_ADDRH, 0); 481 482 val = nlm_read_pci_reg(base, PCIE_BRIDGE_MSI_CAP); 483 /* MSI capability enable at bridge */ 484 nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_CAP, 485 (val | (PCIM_MSICTRL_MSI_ENABLE << 16) | 486 (PCIM_MSICTRL_MMC_32 << 16))); 487 xlpirq = PIC_PCIE_IRQ(link); 488 } 489 490 /* if it is for real PCIe, we need to ack at bridge too */ 491 if (xlpirq >= PIC_PCIE_IRQ(0) && xlpirq <= PIC_PCIE_IRQ(3)) 492 xlp_set_bus_ack(xlpirq, bridge_pcie_ack, NULL); 493 cpu_establish_hardintr(device_get_name(child), filt, intr, arg, 494 xlpirq, flags, cookiep); 495 496 return (0); 497} 498 499static int 500mips_platform_pcib_teardown_intr(device_t dev, device_t child, 501 struct resource *irq, void *cookie) 502{ 503 if (strcmp(device_get_name(child), "pci") == 0) { 504 /* if needed reprogram the pic to clear pcix related entry */ 505 device_printf(dev, "teardown intr\n"); 506 } 507 return (bus_generic_teardown_intr(dev, child, irq, cookie)); 508} 509 510static int 511mips_pcib_route_interrupt(device_t bus, device_t dev, int pin) 512{ 513 int f, d; 514 515 /* 516 * Validate requested pin number. 517 */ 518 if ((pin < 1) || (pin > 4)) 519 return (255); 520 521 if (pci_get_bus(dev) == 0 && 522 pci_get_vendor(dev) == PCI_VENDOR_NETLOGIC) { 523 f = pci_get_function(dev); 524 d = pci_get_slot(dev) % 8; 525 526 /* 527 * For PCIe links, return link IRT, for other SoC devices 528 * get the IRT from its PCIe header 529 */ 530 if (d == 1) 531 return (PIC_PCIE_IRQ(f)); 532 else 533 return (255); /* use intline, don't reroute */ 534 } else { 535 /* Regular PCI devices */ 536 return (PIC_PCIE_IRQ(xlp_pcie_link(bus, dev))); 537 } 538} 539 540static device_method_t xlp_pcib_methods[] = { 541 /* Device interface */ 542 DEVMETHOD(device_probe, xlp_pcib_probe), 543 DEVMETHOD(device_attach, xlp_pcib_attach), 544 545 /* Bus interface */ 546 DEVMETHOD(bus_read_ivar, xlp_pcib_read_ivar), 547 DEVMETHOD(bus_write_ivar, xlp_pcib_write_ivar), 548 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 549 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 550 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 551 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 552 DEVMETHOD(bus_setup_intr, mips_platform_pcib_setup_intr), 553 DEVMETHOD(bus_teardown_intr, mips_platform_pcib_teardown_intr), 554 555 /* pcib interface */ 556 DEVMETHOD(pcib_maxslots, xlp_pcib_maxslots), 557 DEVMETHOD(pcib_read_config, xlp_pcib_read_config), 558 DEVMETHOD(pcib_write_config, xlp_pcib_write_config), 559 DEVMETHOD(pcib_route_interrupt, mips_pcib_route_interrupt), 560 561 DEVMETHOD(pcib_alloc_msi, xlp_alloc_msi), 562 DEVMETHOD(pcib_release_msi, xlp_release_msi), 563 DEVMETHOD(pcib_map_msi, xlp_map_msi), 564 565 DEVMETHOD_END 566}; 567 568static driver_t xlp_pcib_driver = { 569 "pcib", 570 xlp_pcib_methods, 571 1, /* no softc */ 572}; 573 574static devclass_t pcib_devclass; 575DRIVER_MODULE(xlp_pcib, simplebus, xlp_pcib_driver, pcib_devclass, 0, 0); 576