static int of_pci_phb_probe(struct platform_device *dev) { struct pci_controller *phb; /* Check if we can do that ... */ if (ppc_md.pci_setup_phb == NULL) return -ENODEV; pr_info("Setting up PCI bus %s\n", dev->dev.of_node->full_name); /* Alloc and setup PHB data structure */ phb = pcibios_alloc_controller(dev->dev.of_node); if (!phb) return -ENODEV; /* Setup parent in sysfs */ phb->parent = &dev->dev; /* Setup the PHB using arch provided callback */ if (ppc_md.pci_setup_phb(phb)) { pcibios_free_controller(phb); return -ENODEV; } /* Process "ranges" property */ pci_process_bridge_OF_ranges(phb, dev->dev.of_node, 0); /* Init pci_dn data structures */ pci_devs_phb_init_dynamic(phb); /* Create EEH devices for the PHB */ eeh_dev_phb_init_dynamic(phb); /* Register devices with EEH */ if (dev->dev.of_node->child) eeh_add_device_tree_early(dev->dev.of_node); /* Scan the bus */ pcibios_scan_phb(phb); if (phb->bus == NULL) return -ENXIO; /* Claim resources. This might need some rework as well depending * whether we are doing probe-only or not, like assigning unassigned * resources etc... */ pcibios_claim_one_bus(phb->bus); /* Finish EEH setup */ eeh_add_device_tree_late(phb->bus); /* Add probed PCI devices to the device model */ pci_bus_add_devices(phb->bus); /* sysfs files should only be added after devices are added */ eeh_add_sysfs_files(phb->bus); return 0; }
void cxl_pci_vphb_remove(struct cxl_afu *afu) { struct pci_controller *phb; /* If there is no configuration record we won't have one of these */ if (!afu || !afu->phb) return; phb = afu->phb; afu->phb = NULL; pci_remove_root_bus(phb->bus); pcibios_free_controller(phb); }
/* RPA-specific bits for removing PHBs */ int pcibios_remove_root_bus(struct pci_controller *phb) { struct pci_bus *b = phb->bus; struct resource *res; int rc, i; res = b->resource[0]; if (!res->flags) { printk(KERN_ERR "%s: no IO resource for PHB %s\n", __FUNCTION__, b->name); return 1; } rc = unmap_bus_range(b); if (rc) { printk(KERN_ERR "%s: failed to unmap IO on bus %s\n", __FUNCTION__, b->name); return 1; } if (release_resource(res)) { printk(KERN_ERR "%s: failed to release IO on bus %s\n", __FUNCTION__, b->name); return 1; } for (i = 1; i < 3; ++i) { res = b->resource[i]; if (!res->flags && i == 0) { printk(KERN_ERR "%s: no MEM resource for PHB %s\n", __FUNCTION__, b->name); return 1; } if (res->flags && release_resource(res)) { printk(KERN_ERR "%s: failed to release IO %d on bus %s\n", __FUNCTION__, i, b->name); return 1; } } list_del(&phb->list_node); pcibios_free_controller(phb); return 0; }
static void __init ppc4xx_probe_pcix_bridge(struct device_node *np) { struct resource rsrc_cfg; struct resource rsrc_reg; struct resource dma_window; struct pci_controller *hose = NULL; void __iomem *reg = NULL; const int *bus_range; int big_pim = 0, msi = 0, primary = 0; /* Fetch config space registers address */ if (of_address_to_resource(np, 0, &rsrc_cfg)) { printk(KERN_ERR "%s:Can't get PCI-X config register base !", np->full_name); return; } /* Fetch host bridge internal registers address */ if (of_address_to_resource(np, 3, &rsrc_reg)) { printk(KERN_ERR "%s: Can't get PCI-X internal register base !", np->full_name); return; } /* Check if it supports large PIMs (440GX) */ if (of_get_property(np, "large-inbound-windows", NULL)) big_pim = 1; /* Check if we should enable MSIs inbound hole */ if (of_get_property(np, "enable-msi-hole", NULL)) msi = 1; /* Check if primary bridge */ if (of_get_property(np, "primary", NULL)) primary = 1; /* Get bus range if any */ bus_range = of_get_property(np, "bus-range", NULL); /* Map registers */ reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start); if (reg == NULL) { printk(KERN_ERR "%s: Can't map registers !", np->full_name); goto fail; } /* Allocate the host controller data structure */ hose = pcibios_alloc_controller(np); if (!hose) goto fail; hose->first_busno = bus_range ? bus_range[0] : 0x0; hose->last_busno = bus_range ? bus_range[1] : 0xff; /* Setup config space */ setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 0x4, PPC_INDIRECT_TYPE_SET_CFG_TYPE); /* Disable all windows */ writel(0, reg + PCIX0_POM0SA); writel(0, reg + PCIX0_POM1SA); writel(0, reg + PCIX0_POM2SA); writel(0, reg + PCIX0_PIM0SA); writel(0, reg + PCIX0_PIM1SA); writel(0, reg + PCIX0_PIM2SA); if (big_pim) { writel(0, reg + PCIX0_PIM0SAH); writel(0, reg + PCIX0_PIM2SAH); } /* Parse outbound mapping resources */ pci_process_bridge_OF_ranges(hose, np, primary); /* Parse inbound mapping resources */ if (ppc4xx_parse_dma_ranges(hose, reg, &dma_window) != 0) goto fail; /* Configure outbound ranges POMs */ ppc4xx_configure_pcix_POMs(hose, reg); /* Configure inbound ranges PIMs */ ppc4xx_configure_pcix_PIMs(hose, reg, &dma_window, big_pim, msi); /* We don't need the registers anymore */ iounmap(reg); return; fail: if (hose) pcibios_free_controller(hose); if (reg) iounmap(reg); }
static void __init ppc4xx_probe_pci_bridge(struct device_node *np) { /* NYI */ struct resource rsrc_cfg; struct resource rsrc_reg; struct resource dma_window; struct pci_controller *hose = NULL; void __iomem *reg = NULL; const int *bus_range; int primary = 0; /* Check if device is enabled */ if (!of_device_is_available(np)) { printk(KERN_INFO "%s: Port disabled via device-tree\n", np->full_name); return; } /* Fetch config space registers address */ if (of_address_to_resource(np, 0, &rsrc_cfg)) { printk(KERN_ERR "%s: Can't get PCI config register base !", np->full_name); return; } /* Fetch host bridge internal registers address */ if (of_address_to_resource(np, 3, &rsrc_reg)) { printk(KERN_ERR "%s: Can't get PCI internal register base !", np->full_name); return; } /* Check if primary bridge */ if (of_get_property(np, "primary", NULL)) primary = 1; /* Get bus range if any */ bus_range = of_get_property(np, "bus-range", NULL); /* Map registers */ reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start); if (reg == NULL) { printk(KERN_ERR "%s: Can't map registers !", np->full_name); goto fail; } /* Allocate the host controller data structure */ hose = pcibios_alloc_controller(np); if (!hose) goto fail; hose->first_busno = bus_range ? bus_range[0] : 0x0; hose->last_busno = bus_range ? bus_range[1] : 0xff; /* Setup config space */ setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 0x4, 0); /* Disable all windows */ writel(0, reg + PCIL0_PMM0MA); writel(0, reg + PCIL0_PMM1MA); writel(0, reg + PCIL0_PMM2MA); writel(0, reg + PCIL0_PTM1MS); writel(0, reg + PCIL0_PTM2MS); /* Parse outbound mapping resources */ pci_process_bridge_OF_ranges(hose, np, primary); /* Parse inbound mapping resources */ if (ppc4xx_parse_dma_ranges(hose, reg, &dma_window) != 0) goto fail; /* Configure outbound ranges POMs */ ppc4xx_configure_pci_PMMs(hose, reg); /* Configure inbound ranges PIMs */ ppc4xx_configure_pci_PTMs(hose, reg, &dma_window); /* We don't need the registers anymore */ iounmap(reg); return; fail: if (hose) pcibios_free_controller(hose); if (reg) iounmap(reg); }
static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) { struct resource dma_window; struct pci_controller *hose = NULL; const int *bus_range; int primary = 0, busses; void __iomem *mbase = NULL, *cfg_data = NULL; const u32 *pval; u32 val; /* Check if primary bridge */ if (of_get_property(port->node, "primary", NULL)) primary = 1; /* Get bus range if any */ bus_range = of_get_property(port->node, "bus-range", NULL); /* Allocate the host controller data structure */ hose = pcibios_alloc_controller(port->node); if (!hose) goto fail; /* We stick the port number in "indirect_type" so the config space * ops can retrieve the port data structure easily */ hose->indirect_type = port->index; /* Get bus range */ hose->first_busno = bus_range ? bus_range[0] : 0x0; hose->last_busno = bus_range ? bus_range[1] : 0xff; /* Because of how big mapping the config space is (1M per bus), we * limit how many busses we support. In the long run, we could replace * that with something akin to kmap_atomic instead. We set aside 1 bus * for the host itself too. */ busses = hose->last_busno - hose->first_busno; /* This is off by 1 */ if (busses > MAX_PCIE_BUS_MAPPED) { busses = MAX_PCIE_BUS_MAPPED; hose->last_busno = hose->first_busno + busses; } if (!port->endpoint) { /* Only map the external config space in cfg_data for * PCIe root-complexes. External space is 1M per bus */ cfg_data = ioremap(port->cfg_space.start + (hose->first_busno + 1) * 0x100000, busses * 0x100000); if (cfg_data == NULL) { printk(KERN_ERR "%s: Can't map external config space !", port->node->full_name); goto fail; } hose->cfg_data = cfg_data; } /* Always map the host config space in cfg_addr. * Internal space is 4K */ mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000); if (mbase == NULL) { printk(KERN_ERR "%s: Can't map internal config space !", port->node->full_name); goto fail; } hose->cfg_addr = mbase; pr_debug("PCIE %s, bus %d..%d\n", port->node->full_name, hose->first_busno, hose->last_busno); pr_debug(" config space mapped at: root @0x%p, other @0x%p\n", hose->cfg_addr, hose->cfg_data); /* Setup config space */ hose->ops = &ppc4xx_pciex_pci_ops; port->hose = hose; mbase = (void __iomem *)hose->cfg_addr; if (!port->endpoint) { /* * Set bus numbers on our root port */ out_8(mbase + PCI_PRIMARY_BUS, hose->first_busno); out_8(mbase + PCI_SECONDARY_BUS, hose->first_busno + 1); out_8(mbase + PCI_SUBORDINATE_BUS, hose->last_busno); } /* * OMRs are already reset, also disable PIMs */ out_le32(mbase + PECFG_PIMEN, 0); /* Parse outbound mapping resources */ pci_process_bridge_OF_ranges(hose, port->node, primary); /* Parse inbound mapping resources */ if (ppc4xx_parse_dma_ranges(hose, mbase, &dma_window) != 0) goto fail; /* Configure outbound ranges POMs */ ppc4xx_configure_pciex_POMs(port, hose, mbase); /* Configure inbound ranges PIMs */ ppc4xx_configure_pciex_PIMs(port, hose, mbase, &dma_window); /* The root complex doesn't show up if we don't set some vendor * and device IDs into it. The defaults below are the same bogus * one that the initial code in arch/ppc had. This can be * overwritten by setting the "vendor-id/device-id" properties * in the pciex node. */ /* Get the (optional) vendor-/device-id from the device-tree */ pval = of_get_property(port->node, "vendor-id", NULL); if (pval) { val = *pval; } else { if (!port->endpoint) val = 0xaaa0 + port->index; else val = 0xeee0 + port->index; } out_le16(mbase + 0x200, val); pval = of_get_property(port->node, "device-id", NULL); if (pval) { val = *pval; } else { if (!port->endpoint) val = 0xbed0 + port->index; else val = 0xfed0 + port->index; } out_le16(mbase + 0x202, val); if (!port->endpoint) { /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ out_le32(mbase + 0x208, 0x06040001); printk(KERN_INFO "PCIE%d: successfully set as root-complex\n", port->index); } else { /* Set Class Code to Processor/PPC */ out_le32(mbase + 0x208, 0x0b200001); printk(KERN_INFO "PCIE%d: successfully set as endpoint\n", port->index); } return; fail: if (hose) pcibios_free_controller(hose); if (cfg_data) iounmap(cfg_data); if (mbase) iounmap(mbase); }
static int __devinit of_pci_phb_probe(struct of_device *dev, const struct of_device_id *match) { struct pci_controller *phb; /* Check if we can do that ... */ if (ppc_md.pci_setup_phb == NULL) return -ENODEV; printk(KERN_INFO "Setting up PCI bus %s\n", dev->node->full_name); /* Alloc and setup PHB data structure */ phb = pcibios_alloc_controller(dev->node); if (!phb) return -ENODEV; /* Setup parent in sysfs */ phb->parent = &dev->dev; /* Setup the PHB using arch provided callback */ if (ppc_md.pci_setup_phb(phb)) { pcibios_free_controller(phb); return -ENODEV; } /* Process "ranges" property */ pci_process_bridge_OF_ranges(phb, dev->node, 0); /* Setup IO space. We use the non-dynamic version of that code here, * which doesn't quite support unplugging. Next kernel release will * have a better fix for this. * Note also that we don't do ISA, this will also be fixed with a * more massive rework. */ pci_setup_phb_io(phb, pci_io_base == 0); /* Init pci_dn data structures */ pci_devs_phb_init_dynamic(phb); /* Register devices with EEH */ #ifdef CONFIG_EEH if (dev->node->child) eeh_add_device_tree_early(dev->node); #endif /* CONFIG_EEH */ /* Scan the bus */ scan_phb(phb); /* Claim resources. This might need some rework as well depending * wether we are doing probe-only or not, like assigning unassigned * resources etc... */ pcibios_claim_one_bus(phb->bus); /* Finish EEH setup */ #ifdef CONFIG_EEH eeh_add_device_tree_late(phb->bus); #endif /* Add probed PCI devices to the device model */ pci_bus_add_devices(phb->bus); return 0; }
static int __devinit of_pci_phb_probe(struct of_device *dev, const struct of_device_id *match) { struct pci_controller *phb; /* Check if we can do that ... */ if (ppc_md.pci_setup_phb == NULL) return -ENODEV; printk(KERN_INFO "Setting up PCI bus %s\n", dev->node->full_name); /* Alloc and setup PHB data structure */ phb = pcibios_alloc_controller(dev->node); if (!phb) return -ENODEV; /* Setup parent in sysfs */ phb->parent = &dev->dev; /* Setup the PHB using arch provided callback */ if (ppc_md.pci_setup_phb(phb)) { pcibios_free_controller(phb); return -ENODEV; } /* Process "ranges" property */ pci_process_bridge_OF_ranges(phb, dev->node, 0); /* Setup IO space. * This will not work properly for ISA IOs, something needs to be done * about it if we ever generalize that way of probing PCI brigdes */ pci_setup_phb_io_dynamic(phb, 0); /* Init pci_dn data structures */ pci_devs_phb_init_dynamic(phb); /* Register devices with EEH */ #ifdef CONFIG_EEH if (dev->node->child) eeh_add_device_tree_early(dev->node); #endif /* CONFIG_EEH */ /* Scan the bus */ scan_phb(phb); /* Claim resources. This might need some rework as well depending * wether we are doing probe-only or not, like assigning unassigned * resources etc... */ pcibios_claim_one_bus(phb->bus); /* Finish EEH setup */ #ifdef CONFIG_EEH eeh_add_device_tree_late(phb->bus); #endif /* Add probed PCI devices to the device model */ pci_bus_add_devices(phb->bus); return 0; }