1198160Srrs/*- 2198160Srrs * Copyright (c) 2003-2009 RMI Corporation 3198160Srrs * All rights reserved. 4198160Srrs * 5198160Srrs * Redistribution and use in source and binary forms, with or without 6198160Srrs * modification, are permitted provided that the following conditions 7198160Srrs * are met: 8198160Srrs * 1. Redistributions of source code must retain the above copyright 9198160Srrs * notice, this list of conditions and the following disclaimer. 10198160Srrs * 2. Redistributions in binary form must reproduce the above copyright 11198160Srrs * notice, this list of conditions and the following disclaimer in the 12198160Srrs * documentation and/or other materials provided with the distribution. 13198160Srrs * 3. Neither the name of RMI Corporation, nor the names of its contributors, 14198160Srrs * may be used to endorse or promote products derived from this software 15198160Srrs * without specific prior written permission. 16198160Srrs * 17198160Srrs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18198160Srrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19198160Srrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20198160Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21198160Srrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22198160Srrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23198160Srrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24198160Srrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25198160Srrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26198160Srrs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27198160Srrs * SUCH DAMAGE. 28198160Srrs * 29198160Srrs * RMI_BSD */ 30198160Srrs#include <sys/cdefs.h> 31204136Srrs__FBSDID("$FreeBSD$"); 32198160Srrs 33198160Srrs#include <sys/param.h> 34204136Srrs#include <sys/systm.h> 35198160Srrs#include <sys/types.h> 36198160Srrs#include <sys/kernel.h> 37198160Srrs#include <sys/module.h> 38198160Srrs#include <sys/malloc.h> 39198160Srrs#include <sys/bus.h> 40204136Srrs#include <sys/endian.h> 41211994Sjchandra#include <sys/rman.h> 42211994Sjchandra 43198160Srrs#include <vm/vm.h> 44198160Srrs#include <vm/vm_param.h> 45198160Srrs#include <vm/pmap.h> 46198160Srrs 47198160Srrs#include <dev/pci/pcivar.h> 48198160Srrs#include <dev/pci/pcireg.h> 49198160Srrs 50211994Sjchandra#include <machine/bus.h> 51211994Sjchandra#include <machine/md_var.h> 52211994Sjchandra#include <machine/intr_machdep.h> 53211994Sjchandra#include <machine/cpuregs.h> 54211994Sjchandra 55211994Sjchandra#include <mips/rmi/rmi_mips_exts.h> 56211994Sjchandra#include <mips/rmi/interrupt.h> 57198607Srrs#include <mips/rmi/iomap.h> 58198607Srrs#include <mips/rmi/pic.h> 59198607Srrs#include <mips/rmi/board.h> 60198607Srrs#include <mips/rmi/pcibus.h> 61204136Srrs 62198160Srrs#include "pcib_if.h" 63198160Srrs 64204136Srrs#define pci_cfg_offset(bus,slot,devfn,where) (((bus)<<16) + ((slot) << 11)+((devfn)<<8)+(where)) 65204136Srrs#define PCIE_LINK_STATE 0x4000 66204136Srrs 67198160Srrs#define LSU_CFG0_REGID 0 68198160Srrs#define LSU_CERRLOG_REGID 9 69198160Srrs#define LSU_CERROVF_REGID 10 70198160Srrs#define LSU_CERRINT_REGID 11 71198160Srrs 72198160Srrs/* MSI support */ 73204136Srrs#define MSI_MIPS_ADDR_DEST 0x000ff000 74204136Srrs#define MSI_MIPS_ADDR_RH 0x00000008 75204136Srrs#define MSI_MIPS_ADDR_RH_OFF 0x00000000 76204136Srrs#define MSI_MIPS_ADDR_RH_ON 0x00000008 77204136Srrs#define MSI_MIPS_ADDR_DM 0x00000004 78204136Srrs#define MSI_MIPS_ADDR_DM_PHYSICAL 0x00000000 79204136Srrs#define MSI_MIPS_ADDR_DM_LOGICAL 0x00000004 80198160Srrs 81198160Srrs/* Fields in data for Intel MSI messages. */ 82204136Srrs#define MSI_MIPS_DATA_TRGRMOD 0x00008000 /* Trigger mode */ 83204136Srrs#define MSI_MIPS_DATA_TRGREDG 0x00000000 /* edge */ 84204136Srrs#define MSI_MIPS_DATA_TRGRLVL 0x00008000 /* level */ 85198160Srrs 86204136Srrs#define MSI_MIPS_DATA_LEVEL 0x00004000 /* Polarity. */ 87204136Srrs#define MSI_MIPS_DATA_DEASSERT 0x00000000 88204136Srrs#define MSI_MIPS_DATA_ASSERT 0x00004000 89198160Srrs 90204136Srrs#define MSI_MIPS_DATA_DELMOD 0x00000700 /* Delivery Mode */ 91204136Srrs#define MSI_MIPS_DATA_DELFIXED 0x00000000 /* fixed */ 92204136Srrs#define MSI_MIPS_DATA_DELLOPRI 0x00000100 /* lowest priority */ 93198160Srrs 94204136Srrs#define MSI_MIPS_DATA_INTVEC 0x000000ff 95198160Srrs 96198160Srrs/* 97198160Srrs * Build Intel MSI message and data values from a source. AMD64 systems 98198160Srrs * seem to be compatible, so we use the same function for both. 99198160Srrs */ 100198160Srrs#define MIPS_MSI_ADDR(cpu) \ 101198160Srrs (MSI_MIPS_ADDR_BASE | (cpu) << 12 | \ 102198160Srrs MSI_MIPS_ADDR_RH_OFF | MSI_MIPS_ADDR_DM_PHYSICAL) 103198160Srrs 104198160Srrs#define MIPS_MSI_DATA(irq) \ 105198160Srrs (MSI_MIPS_DATA_TRGRLVL | MSI_MIPS_DATA_DELFIXED | \ 106198160Srrs MSI_MIPS_DATA_ASSERT | (irq)) 107198160Srrs 108204136Srrsstruct xlr_pcib_softc { 109213484Sjchandra bus_dma_tag_t sc_pci_dmat; /* PCI DMA tag pointer */ 110198160Srrs}; 111204136Srrs 112198625Srrsstatic devclass_t pcib_devclass; 113204136Srrsstatic void *xlr_pci_config_base; 114204136Srrsstatic struct rman irq_rman, port_rman, mem_rman; 115198160Srrs 116204136Srrsstatic void 117204136Srrsxlr_pci_init_resources(void) 118204136Srrs{ 119211811Sjchandra 120204136Srrs irq_rman.rm_start = 0; 121204136Srrs irq_rman.rm_end = 255; 122204136Srrs irq_rman.rm_type = RMAN_ARRAY; 123204136Srrs irq_rman.rm_descr = "PCI Mapped Interrupts"; 124204136Srrs if (rman_init(&irq_rman) 125204136Srrs || rman_manage_region(&irq_rman, 0, 255)) 126204136Srrs panic("pci_init_resources irq_rman"); 127198160Srrs 128204136Srrs port_rman.rm_start = 0; 129221218Sjhb port_rman.rm_end = ~0ul; 130204136Srrs port_rman.rm_type = RMAN_ARRAY; 131204136Srrs port_rman.rm_descr = "I/O ports"; 132204136Srrs if (rman_init(&port_rman) 133204136Srrs || rman_manage_region(&port_rman, 0x10000000, 0x1fffffff)) 134204136Srrs panic("pci_init_resources port_rman"); 135204136Srrs 136204136Srrs mem_rman.rm_start = 0; 137221218Sjhb mem_rman.rm_end = ~0ul; 138204136Srrs mem_rman.rm_type = RMAN_ARRAY; 139204136Srrs mem_rman.rm_descr = "I/O memory"; 140204136Srrs if (rman_init(&mem_rman) 141204136Srrs || rman_manage_region(&mem_rman, 0xd0000000, 0xdfffffff)) 142204136Srrs panic("pci_init_resources mem_rman"); 143204136Srrs} 144204136Srrs 145198160Srrsstatic int 146198160Srrsxlr_pcib_probe(device_t dev) 147198160Srrs{ 148211811Sjchandra 149204136Srrs if (xlr_board_info.is_xls) 150204136Srrs device_set_desc(dev, "XLS PCIe bus"); 151204136Srrs else 152204136Srrs device_set_desc(dev, "XLR PCI bus"); 153198160Srrs 154204136Srrs xlr_pci_init_resources(); 155204136Srrs xlr_pci_config_base = (void *)MIPS_PHYS_TO_KSEG1(DEFAULT_PCI_CONFIG_BASE); 156198160Srrs 157211811Sjchandra return (0); 158198160Srrs} 159198160Srrs 160198160Srrsstatic int 161204136Srrsxlr_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 162198160Srrs{ 163211811Sjchandra 164198160Srrs switch (which) { 165204136Srrs case PCIB_IVAR_DOMAIN: 166204136Srrs *result = 0; 167204136Srrs return (0); 168198625Srrs case PCIB_IVAR_BUS: 169198160Srrs *result = 0; 170204136Srrs return (0); 171198160Srrs } 172204136Srrs return (ENOENT); 173198160Srrs} 174198160Srrs 175198160Srrsstatic int 176204136Srrsxlr_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t result) 177204136Srrs{ 178204136Srrs switch (which) { 179204136Srrs case PCIB_IVAR_DOMAIN: 180204136Srrs return (EINVAL); 181204136Srrs case PCIB_IVAR_BUS: 182204136Srrs return (EINVAL); 183204136Srrs } 184204136Srrs return (ENOENT); 185204136Srrs} 186204136Srrs 187204136Srrsstatic int 188198160Srrsxlr_pcib_maxslots(device_t dev) 189198160Srrs{ 190211811Sjchandra 191204136Srrs return (PCI_SLOTMAX); 192198160Srrs} 193198160Srrs 194198625Srrsstatic __inline__ void 195198625Srrsdisable_and_clear_cache_error(void) 196198625Srrs{ 197211811Sjchandra uint64_t lsu_cfg0; 198198625Srrs 199212366Sjchandra lsu_cfg0 = read_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CFG0_REGID); 200198625Srrs lsu_cfg0 = lsu_cfg0 & ~0x2e; 201212366Sjchandra write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CFG0_REGID, lsu_cfg0); 202198625Srrs /* Clear cache error log */ 203212366Sjchandra write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CERRLOG_REGID, 0); 204198160Srrs} 205198160Srrs 206198625Srrsstatic __inline__ void 207198625Srrsclear_and_enable_cache_error(void) 208198625Srrs{ 209198625Srrs uint64_t lsu_cfg0 = 0; 210198160Srrs 211198625Srrs /* first clear the cache error logging register */ 212212366Sjchandra write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CERRLOG_REGID, 0); 213212366Sjchandra write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CERROVF_REGID, 0); 214212366Sjchandra write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CERRINT_REGID, 0); 215198160Srrs 216212366Sjchandra lsu_cfg0 = read_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CFG0_REGID); 217198625Srrs lsu_cfg0 = lsu_cfg0 | 0x2e; 218212366Sjchandra write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CFG0_REGID, lsu_cfg0); 219198160Srrs} 220198160Srrs 221198625Srrsstatic uint32_t 222204136Srrspci_cfg_read_32bit(uint32_t addr) 223198160Srrs{ 224204136Srrs uint32_t temp = 0; 225209808Sjchandra uint32_t *p = (uint32_t *)xlr_pci_config_base + addr / sizeof(uint32_t); 226204136Srrs uint64_t cerr_cpu_log = 0; 227204136Srrs 228204136Srrs disable_and_clear_cache_error(); 229204136Srrs temp = bswap32(*p); 230204136Srrs 231204136Srrs /* Read cache err log */ 232212366Sjchandra cerr_cpu_log = read_xlr_ctrl_register(CPU_BLOCKID_LSU, 233211811Sjchandra LSU_CERRLOG_REGID); 234204136Srrs if (cerr_cpu_log) { 235204136Srrs /* Device don't exist. */ 236204136Srrs temp = ~0x0; 237204136Srrs } 238204136Srrs clear_and_enable_cache_error(); 239211811Sjchandra return (temp); 240204136Srrs} 241204136Srrs 242204136Srrsstatic u_int32_t 243204136Srrsxlr_pcib_read_config(device_t dev, u_int b, u_int s, u_int f, 244204136Srrs u_int reg, int width) 245204136Srrs{ 246198625Srrs uint32_t data = 0; 247198160Srrs 248198160Srrs if ((width == 2) && (reg & 1)) 249198160Srrs return 0xFFFFFFFF; 250198160Srrs else if ((width == 4) && (reg & 3)) 251198160Srrs return 0xFFFFFFFF; 252198160Srrs 253204136Srrs data = pci_cfg_read_32bit(pci_cfg_offset(b, s, f, reg)); 254198160Srrs 255198160Srrs if (width == 1) 256198160Srrs return ((data >> ((reg & 3) << 3)) & 0xff); 257198160Srrs else if (width == 2) 258198160Srrs return ((data >> ((reg & 3) << 3)) & 0xffff); 259198160Srrs else 260211811Sjchandra return (data); 261198160Srrs} 262198160Srrs 263204136Srrsstatic void 264204136Srrsxlr_pcib_write_config(device_t dev, u_int b, u_int s, u_int f, 265204136Srrs u_int reg, u_int32_t val, int width) 266198625Srrs{ 267198160Srrs uint32_t cfgaddr = pci_cfg_offset(b, s, f, reg); 268204136Srrs uint32_t data = 0, *p; 269198160Srrs 270198160Srrs if ((width == 2) && (reg & 1)) 271198625Srrs return; 272198160Srrs else if ((width == 4) && (reg & 3)) 273198625Srrs return; 274198160Srrs 275198160Srrs if (width == 1) { 276198160Srrs data = pci_cfg_read_32bit(cfgaddr); 277198160Srrs data = (data & ~(0xff << ((reg & 3) << 3))) | 278198160Srrs (val << ((reg & 3) << 3)); 279198160Srrs } else if (width == 2) { 280198160Srrs data = pci_cfg_read_32bit(cfgaddr); 281198160Srrs data = (data & ~(0xffff << ((reg & 3) << 3))) | 282198160Srrs (val << ((reg & 3) << 3)); 283198160Srrs } else { 284198625Srrs data = val; 285198160Srrs } 286198160Srrs 287209808Sjchandra p = (uint32_t *)xlr_pci_config_base + cfgaddr / sizeof(uint32_t); 288204136Srrs *p = bswap32(data); 289198160Srrs 290198625Srrs return; 291198160Srrs} 292198160Srrs 293198625Srrsstatic int 294198625Srrsxlr_pcib_attach(device_t dev) 295198160Srrs{ 296213484Sjchandra struct xlr_pcib_softc *sc; 297213484Sjchandra sc = device_get_softc(dev); 298213484Sjchandra 299213484Sjchandra /* 300213484Sjchandra * XLR C revision chips cannot do DMA above 2G physical address 301213484Sjchandra * create a parent tag with this lowaddr 302213484Sjchandra */ 303213484Sjchandra if (xlr_is_c_revision()) { 304213484Sjchandra if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, 305213484Sjchandra 0x7fffffff, ~0, NULL, NULL, 0x7fffffff, 306213484Sjchandra 0xff, 0x7fffffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0) 307213484Sjchandra panic("%s: bus_dma_tag_create failed", __func__); 308213484Sjchandra } 309198160Srrs device_add_child(dev, "pci", 0); 310198160Srrs bus_generic_attach(dev); 311211811Sjchandra return (0); 312198160Srrs} 313198160Srrs 314198160Srrsstatic void 315198625Srrsxlr_pcib_identify(driver_t * driver, device_t parent) 316198160Srrs{ 317211811Sjchandra 318198625Srrs BUS_ADD_CHILD(parent, 0, "pcib", 0); 319198160Srrs} 320198160Srrs 321212285Sjchandra/* 322212285Sjchandra * XLS PCIe can have upto 4 links, and each link has its on IRQ 323212285Sjchandra * Find the link on which the device is on 324212285Sjchandra */ 325198160Srrsstatic int 326212285Sjchandraxls_pcie_link(device_t pcib, device_t dev) 327198160Srrs{ 328198160Srrs device_t parent, tmp; 329198160Srrs 330198160Srrs /* find the lane on which the slot is connected to */ 331212285Sjchandra printf("xls_pcie_link : bus %s dev %s\n", device_get_nameunit(pcib), 332212285Sjchandra device_get_nameunit(dev)); 333198160Srrs tmp = dev; 334198160Srrs while (1) { 335198625Srrs parent = device_get_parent(tmp); 336198160Srrs if (parent == NULL || parent == pcib) { 337198625Srrs device_printf(dev, "Cannot find parent bus\n"); 338212285Sjchandra return (-1); 339198160Srrs } 340198160Srrs if (strcmp(device_get_nameunit(parent), "pci0") == 0) 341198160Srrs break; 342198160Srrs tmp = parent; 343198160Srrs } 344212285Sjchandra return (pci_get_slot(tmp)); 345212285Sjchandra} 346198160Srrs 347212285Sjchandra/* 348212285Sjchandra * Find the IRQ for the link, each link has a different interrupt 349212285Sjchandra * at the XLS pic 350212285Sjchandra */ 351212285Sjchandrastatic int 352212285Sjchandraxls_pcie_link_irq(int link) 353212285Sjchandra{ 354212285Sjchandra 355212285Sjchandra switch (link) { 356198625Srrs case 0: 357212285Sjchandra return (PIC_PCIE_LINK0_IRQ); 358198625Srrs case 1: 359212285Sjchandra return (PIC_PCIE_LINK1_IRQ); 360198625Srrs case 2: 361213199Sjchandra if (xlr_is_xls_b0()) 362213199Sjchandra return (PIC_PCIE_B0_LINK2_IRQ); 363213199Sjchandra else 364213199Sjchandra return (PIC_PCIE_LINK2_IRQ); 365198625Srrs case 3: 366213199Sjchandra if (xlr_is_xls_b0()) 367213199Sjchandra return (PIC_PCIE_B0_LINK3_IRQ); 368213199Sjchandra else 369213199Sjchandra return (PIC_PCIE_LINK3_IRQ); 370198160Srrs } 371212285Sjchandra return (-1); 372212285Sjchandra} 373198160Srrs 374212285Sjchandrastatic int 375212285Sjchandraxlr_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs) 376212285Sjchandra{ 377212285Sjchandra int i, link; 378212285Sjchandra 379198625Srrs /* 380212285Sjchandra * Each link has 32 MSIs that can be allocated, but for now 381212285Sjchandra * we only support one device per link. 382212285Sjchandra * msi_alloc() equivalent is needed when we start supporting 383212285Sjchandra * bridges on the PCIe link. 384198625Srrs */ 385212285Sjchandra link = xls_pcie_link(pcib, dev); 386212285Sjchandra if (link == -1) 387212285Sjchandra return (ENXIO); 388198160Srrs 389212285Sjchandra /* 390212285Sjchandra * encode the irq so that we know it is a MSI interrupt when we 391212285Sjchandra * setup interrupts 392212285Sjchandra */ 393212285Sjchandra for (i = 0; i < count; i++) 394212285Sjchandra irqs[i] = 64 + link * 32 + i; 395212285Sjchandra 396211811Sjchandra return (0); 397198160Srrs} 398198160Srrs 399198160Srrsstatic int 400198160Srrsxlr_release_msi(device_t pcib, device_t dev, int count, int *irqs) 401198160Srrs{ 402211811Sjchandra device_printf(dev, "%s: msi release %d\n", device_get_nameunit(pcib), 403211811Sjchandra count); 404211811Sjchandra return (0); 405198160Srrs} 406198160Srrs 407198160Srrsstatic int 408212285Sjchandraxlr_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, 409212285Sjchandra uint32_t *data) 410198160Srrs{ 411212285Sjchandra int msi; 412211811Sjchandra 413212285Sjchandra if (irq >= 64) { 414212285Sjchandra msi = irq - 64; 415198160Srrs *addr = MIPS_MSI_ADDR(0); 416212285Sjchandra *data = MIPS_MSI_DATA(msi); 417211811Sjchandra return (0); 418212285Sjchandra } else { 419211811Sjchandra device_printf(dev, "%s: map_msi for irq %d - ignored", 420211811Sjchandra device_get_nameunit(pcib), irq); 421198160Srrs return (ENXIO); 422198160Srrs } 423198160Srrs} 424198160Srrs 425204136Srrsstatic void 426211893Sjchandrabridge_pcix_ack(int irq) 427204136Srrs{ 428211811Sjchandra 429217625Sjchandra (void)xlr_read_reg(xlr_io_mmio(XLR_IO_PCIX_OFFSET), 0x140 >> 2); 430204136Srrs} 431204136Srrs 432204136Srrsstatic void 433211893Sjchandrabridge_pcie_ack(int irq) 434204136Srrs{ 435204136Srrs uint32_t reg; 436204136Srrs xlr_reg_t *pcie_mmio_le = xlr_io_mmio(XLR_IO_PCIE_1_OFFSET); 437204136Srrs 438204136Srrs switch (irq) { 439211811Sjchandra case PIC_PCIE_LINK0_IRQ: 440211811Sjchandra reg = PCIE_LINK0_MSI_STATUS; 441211811Sjchandra break; 442211811Sjchandra case PIC_PCIE_LINK1_IRQ: 443211811Sjchandra reg = PCIE_LINK1_MSI_STATUS; 444211811Sjchandra break; 445211811Sjchandra case PIC_PCIE_LINK2_IRQ: 446213199Sjchandra case PIC_PCIE_B0_LINK2_IRQ: 447211811Sjchandra reg = PCIE_LINK2_MSI_STATUS; 448211811Sjchandra break; 449211811Sjchandra case PIC_PCIE_LINK3_IRQ: 450213199Sjchandra case PIC_PCIE_B0_LINK3_IRQ: 451211811Sjchandra reg = PCIE_LINK3_MSI_STATUS; 452211811Sjchandra break; 453204136Srrs default: 454204136Srrs return; 455204136Srrs } 456204136Srrs xlr_write_reg(pcie_mmio_le, reg>>2, 0xffffffff); 457204136Srrs} 458204136Srrs 459204136Srrsstatic int 460204136Srrsmips_platform_pci_setup_intr(device_t dev, device_t child, 461212285Sjchandra struct resource *irq, int flags, driver_filter_t *filt, 462212285Sjchandra driver_intr_t *intr, void *arg, void **cookiep) 463204136Srrs{ 464204136Srrs int error = 0; 465204136Srrs int xlrirq; 466204136Srrs 467204136Srrs error = rman_activate_resource(irq); 468204136Srrs if (error) 469204136Srrs return error; 470204136Srrs if (rman_get_start(irq) != rman_get_end(irq)) { 471204136Srrs device_printf(dev, "Interrupt allocation %lu != %lu\n", 472204136Srrs rman_get_start(irq), rman_get_end(irq)); 473211811Sjchandra return (EINVAL); 474204136Srrs } 475204136Srrs xlrirq = rman_get_start(irq); 476204136Srrs 477204136Srrs if (strcmp(device_get_name(dev), "pcib") != 0) 478211811Sjchandra return (0); 479204136Srrs 480204136Srrs if (xlr_board_info.is_xls == 0) { 481211893Sjchandra xlr_establish_intr(device_get_name(child), filt, 482211893Sjchandra intr, arg, PIC_PCIX_IRQ, flags, cookiep, bridge_pcix_ack); 483212248Sjchandra pic_setup_intr(PIC_IRT_PCIX_INDEX, PIC_PCIX_IRQ, 0x1, 1); 484204136Srrs } else { 485212285Sjchandra /* 486212285Sjchandra * temporary hack for MSI, we support just one device per 487212285Sjchandra * link, and assign the link interrupt to the device interrupt 488212285Sjchandra */ 489212285Sjchandra if (xlrirq >= 64) { 490212285Sjchandra xlrirq -= 64; 491212285Sjchandra if (xlrirq % 32 != 0) 492212285Sjchandra return (0); 493212285Sjchandra xlrirq = xls_pcie_link_irq(xlrirq / 32); 494212285Sjchandra if (xlrirq == -1) 495212285Sjchandra return (EINVAL); 496212285Sjchandra } 497211893Sjchandra xlr_establish_intr(device_get_name(child), filt, 498211893Sjchandra intr, arg, xlrirq, flags, cookiep, bridge_pcie_ack); 499212248Sjchandra pic_setup_intr(xlrirq - PIC_IRQ_BASE, xlrirq, 0x1, 1); 500204136Srrs } 501204136Srrs 502211811Sjchandra return (bus_generic_setup_intr(dev, child, irq, flags, filt, intr, 503211811Sjchandra arg, cookiep)); 504204136Srrs} 505204136Srrs 506204136Srrsstatic int 507204136Srrsmips_platform_pci_teardown_intr(device_t dev, device_t child, 508204136Srrs struct resource *irq, void *cookie) 509204136Srrs{ 510204136Srrs if (strcmp(device_get_name(child), "pci") == 0) { 511204136Srrs /* if needed reprogram the pic to clear pcix related entry */ 512204136Srrs device_printf(dev, "teardown intr\n"); 513204136Srrs } 514211811Sjchandra return (bus_generic_teardown_intr(dev, child, irq, cookie)); 515204136Srrs} 516204136Srrs 517204136Srrsstatic struct resource * 518204136Srrsxlr_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, 519204136Srrs u_long start, u_long end, u_long count, u_int flags) 520204136Srrs{ 521204136Srrs struct rman *rm; 522204136Srrs struct resource *rv; 523204136Srrs vm_offset_t va; 524204136Srrs int needactivate = flags & RF_ACTIVE; 525204136Srrs 526204136Srrs switch (type) { 527204136Srrs case SYS_RES_IRQ: 528204136Srrs rm = &irq_rman; 529204136Srrs break; 530204136Srrs 531204136Srrs case SYS_RES_IOPORT: 532204136Srrs rm = &port_rman; 533204136Srrs break; 534204136Srrs 535204136Srrs case SYS_RES_MEMORY: 536204136Srrs rm = &mem_rman; 537204136Srrs break; 538204136Srrs 539204136Srrs default: 540211811Sjchandra return (0); 541204136Srrs } 542204136Srrs 543204136Srrs rv = rman_reserve_resource(rm, start, end, count, flags, child); 544204136Srrs if (rv == 0) 545211811Sjchandra return (0); 546204136Srrs 547204136Srrs rman_set_rid(rv, *rid); 548204136Srrs 549204136Srrs if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { 550204136Srrs va = (vm_offset_t)pmap_mapdev(start, count); 551204136Srrs rman_set_bushandle(rv, va); 552204136Srrs /* bushandle is same as virtual addr */ 553204136Srrs rman_set_virtual(rv, (void *)va); 554204136Srrs rman_set_bustag(rv, rmi_pci_bus_space); 555204136Srrs } 556204136Srrs 557204136Srrs if (needactivate) { 558204136Srrs if (bus_activate_resource(child, type, *rid, rv)) { 559204136Srrs rman_release_resource(rv); 560204136Srrs return (NULL); 561204136Srrs } 562204136Srrs } 563211811Sjchandra return (rv); 564204136Srrs} 565204136Srrs 566204136Srrsstatic int 567204136Srrsxlr_pci_release_resource(device_t bus, device_t child, int type, int rid, 568204136Srrs struct resource *r) 569204136Srrs{ 570211811Sjchandra 571204136Srrs return (rman_release_resource(r)); 572204136Srrs} 573204136Srrs 574213484Sjchandrastatic bus_dma_tag_t 575213484Sjchandraxlr_pci_get_dma_tag(device_t bus, device_t child) 576213484Sjchandra{ 577213484Sjchandra struct xlr_pcib_softc *sc; 578213484Sjchandra 579213484Sjchandra sc = device_get_softc(bus); 580213484Sjchandra return (sc->sc_pci_dmat); 581213484Sjchandra} 582213484Sjchandra 583204136Srrsstatic int 584204136Srrsxlr_pci_activate_resource(device_t bus, device_t child, int type, int rid, 585204136Srrs struct resource *r) 586204136Srrs{ 587211811Sjchandra 588204136Srrs return (rman_activate_resource(r)); 589204136Srrs} 590204136Srrs 591204136Srrsstatic int 592204136Srrsxlr_pci_deactivate_resource(device_t bus, device_t child, int type, int rid, 593204136Srrs struct resource *r) 594204136Srrs{ 595211811Sjchandra 596204136Srrs return (rman_deactivate_resource(r)); 597204136Srrs} 598204136Srrs 599204136Srrsstatic int 600204136Srrsmips_pci_route_interrupt(device_t bus, device_t dev, int pin) 601204136Srrs{ 602212285Sjchandra int irq, link; 603211811Sjchandra 604204136Srrs /* 605204136Srrs * Validate requested pin number. 606204136Srrs */ 607204136Srrs if ((pin < 1) || (pin > 4)) 608204136Srrs return (255); 609204136Srrs 610204136Srrs if (xlr_board_info.is_xls) { 611212285Sjchandra link = xls_pcie_link(bus, dev); 612212285Sjchandra irq = xls_pcie_link_irq(link); 613212285Sjchandra if (irq != -1) 614212285Sjchandra return (irq); 615204136Srrs } else { 616212285Sjchandra if (pin == 1) 617212285Sjchandra return (PIC_PCIX_IRQ); 618204136Srrs } 619204136Srrs 620204136Srrs return (255); 621204136Srrs} 622204136Srrs 623198160Srrsstatic device_method_t xlr_pcib_methods[] = { 624198160Srrs /* Device interface */ 625198625Srrs DEVMETHOD(device_identify, xlr_pcib_identify), 626198625Srrs DEVMETHOD(device_probe, xlr_pcib_probe), 627198625Srrs DEVMETHOD(device_attach, xlr_pcib_attach), 628198160Srrs 629198160Srrs /* Bus interface */ 630198625Srrs DEVMETHOD(bus_read_ivar, xlr_pcib_read_ivar), 631204136Srrs DEVMETHOD(bus_write_ivar, xlr_pcib_write_ivar), 632198625Srrs DEVMETHOD(bus_alloc_resource, xlr_pci_alloc_resource), 633204136Srrs DEVMETHOD(bus_release_resource, xlr_pci_release_resource), 634213484Sjchandra DEVMETHOD(bus_get_dma_tag, xlr_pci_get_dma_tag), 635204136Srrs DEVMETHOD(bus_activate_resource, xlr_pci_activate_resource), 636204136Srrs DEVMETHOD(bus_deactivate_resource, xlr_pci_deactivate_resource), 637198625Srrs DEVMETHOD(bus_setup_intr, mips_platform_pci_setup_intr), 638204136Srrs DEVMETHOD(bus_teardown_intr, mips_platform_pci_teardown_intr), 639198160Srrs 640198160Srrs /* pcib interface */ 641198625Srrs DEVMETHOD(pcib_maxslots, xlr_pcib_maxslots), 642198625Srrs DEVMETHOD(pcib_read_config, xlr_pcib_read_config), 643198625Srrs DEVMETHOD(pcib_write_config, xlr_pcib_write_config), 644198625Srrs DEVMETHOD(pcib_route_interrupt, mips_pci_route_interrupt), 645198160Srrs 646198625Srrs DEVMETHOD(pcib_alloc_msi, xlr_alloc_msi), 647198625Srrs DEVMETHOD(pcib_release_msi, xlr_release_msi), 648198625Srrs DEVMETHOD(pcib_map_msi, xlr_map_msi), 649198625Srrs 650227843Smarius DEVMETHOD_END 651198160Srrs}; 652198160Srrs 653198160Srrsstatic driver_t xlr_pcib_driver = { 654198160Srrs "pcib", 655198160Srrs xlr_pcib_methods, 656204136Srrs sizeof(struct xlr_pcib_softc), 657198160Srrs}; 658198160Srrs 659208165SrrsDRIVER_MODULE(pcib, iodi, xlr_pcib_driver, pcib_devclass, 0, 0); 660