/* if we aren't a PCIe don't bother */ if (!pci_is_pcie(dev)) return;
/* if we aren't in host mode don't bother */
pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type); if ((hdr_type & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_BRIDGE) return;
staticvoid fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
{ /* * Fix up PCI devices that are able to DMA to the large inbound * mapping that allows addressing any RAM address from across PCI.
*/ if (dev_is_pci(dev) && dma_mask >= pci64_dma_offset * 2 - 1) {
dev->bus_dma_limit = 0;
dev->archdata.dma_offset = pci64_dma_offset;
}
}
/* * If this is kdump, we don't want to trigger a bunch of PCI * errors by closing the window on in-flight DMA. * * We still run most of the function's logic so that things like * hose->dma_window_size still get set.
*/
setup_inbound = !is_kdump();
if (of_device_is_compatible(hose->dn, "fsl,bsc9132-pcie")) { /* * BSC9132 Rev1.0 has an issue where all the PEX inbound * windows have implemented the default target value as 0xf * for CCSR space.In all Freescale legacy devices the target * of 0xf is reserved for local memory space. 9132 Rev1.0 * now has local memory space mapped to target 0x0 instead of * 0xf. Hence adding a workaround to remove the target 0xf * defined for memory space from Inbound window attributes.
*/
piwar &= ~PIWAR_TGI_LOCAL;
}
/* Setup inbound mem window */
mem = memblock_end_of_DRAM();
pr_info("%s: end of DRAM %llx\n", __func__, mem);
/* * The msi-address-64 property, if it exists, indicates the physical * address of the MSIIR register. Normally, this register is located * inside CCSR, so the ATMU that covers all of CCSR is used. But if * this property exists, then we normally need to create a new ATMU * for it. For now, however, we cheat. The only entity that creates * this property is the Freescale hypervisor, and the address is * specified in the partition configuration. Typically, the address * is located in the page immediately after the end of DDR. If so, we * can avoid allocating a new ATMU by extending the DDR ATMU by one * page.
*/
reg = of_get_property(hose->dn, "msi-address-64", &len); if (reg && (len == sizeof(u64))) {
u64 address = be64_to_cpup(reg);
if ((address >= mem) && (address < (mem + PAGE_SIZE))) {
pr_info("%pOF: extending DDR ATMU to cover MSIIR", hose->dn);
mem += PAGE_SIZE;
} else { /* TODO: Create a new ATMU for MSIIR */
pr_warn("%pOF: msi-address-64 address of %llx is " "unsupported\n", hose->dn, address);
}
}
sz = min(mem, paddr_lo);
mem_log = ilog2(sz);
/* PCIe can overmap inbound & outbound since RX & TX are separated */ if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { /* Size window to exact size if power-of-two or one size up */ if ((1ull << mem_log) != mem) {
mem_log++; if ((1ull << mem_log) > mem)
pr_info("%pOF: Setting PCI inbound window " "greater than memory size\n", hose->dn);
}
/* * if we have >4G of memory setup second PCI inbound window to * let devices that are 64-bit address capable to work w/o * SWIOTLB and access the full range of memory
*/ if (sz != mem) {
mem_log = ilog2(mem);
/* Size window up if we dont fit in exact power-of-2 */ if ((1ull << mem_log) != mem)
mem_log++;
void fsl_pcibios_fixup_bus(struct pci_bus *bus)
{ struct pci_controller *hose = pci_bus_to_host(bus); int i, is_pcie = 0, no_link;
/* The root complex bridge comes up with bogus resources, * we copy the PHB ones in. * * With the current generic PCI code, the PHB bus no longer * has bus->resource[0..4] set, so things are a bit more * tricky.
*/
/* Get bus range if any */
bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int))
printk(KERN_WARNING "Can't get bus-range for %pOF, assume" " bus 0\n", dev);
pci_add_flags(PCI_REASSIGN_ALL_BUS);
hose = pcibios_alloc_controller(dev); if (!hose) return -ENOMEM;
/* set platform device as the parent */
hose->parent = &pdev->dev;
hose->first_busno = bus_range ? bus_range[0] : 0x0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;
if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0)
hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK;
if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { /* use fsl_indirect_read_config for PCIe */
hose->ops = &fsl_indirect_pcie_ops; /* For PCIE read HEADER_TYPE to identify controller mode */
early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type); if ((hdr_type & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_BRIDGE) goto no_bridge;
} else { /* For PCI read PROG to identify controller mode */
early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, &progif); if ((progif & 1) &&
!of_property_read_bool(dev, "fsl,pci-agent-force-enum")) goto no_bridge;
}
setup_pci_cmd(hose);
/* check PCI express link status */ if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
hose->indirect_type |= PPC_INDIRECT_TYPE_EXT_REG |
PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS; if (fsl_pcie_check_link(hose))
hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; /* Fix Class Code to PCI_CLASS_BRIDGE_PCI_NORMAL for pre-3.0 controller */ if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0) {
early_read_config_dword(hose, 0, 0, PCIE_FSL_CSR_CLASSCODE, &class_code);
class_code &= 0xff;
class_code |= PCI_CLASS_BRIDGE_PCI_NORMAL << 8;
early_write_config_dword(hose, 0, 0, PCIE_FSL_CSR_CLASSCODE, class_code);
}
} else { /* * Set PBFR(PCI Bus Function Register)[10] = 1 to * disable the combining of crossing cacheline * boundary requests into one burst transaction. * PCI-X operation is not affected. * Fix erratum PCI 5 on MPC8548
*/ #define PCI_BUS_FUNCTION 0x44 #define PCI_BUS_FUNCTION_MDS 0x400 /* Master disable streaming */ if (((SVR_SOC_VER(svr) == SVR_8543) ||
(SVR_SOC_VER(svr) == SVR_8545) ||
(SVR_SOC_VER(svr) == SVR_8547) ||
(SVR_SOC_VER(svr) == SVR_8548)) &&
!early_find_capability(hose, 0, 0, PCI_CAP_ID_PCIX)) {
early_read_config_word(hose, 0, 0,
PCI_BUS_FUNCTION, &temp);
temp |= PCI_BUS_FUNCTION_MDS;
early_write_config_word(hose, 0, 0,
PCI_BUS_FUNCTION, temp);
}
}
printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. " "Firmware bus number: %d->%d\n",
(unsignedlonglong)rsrc.start, hose->first_busno,
hose->last_busno);
pr_debug(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
hose, hose->cfg_addr, hose->cfg_data);
/* Interpret the "ranges" property */ /* This also maps the I/O region and sets isa_io/mem_base */
pci_process_bridge_OF_ranges(hose, dev, is_primary);
if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK) return PCIBIOS_DEVICE_NOT_FOUND; /* * Workaround for the HW bug: for Type 0 configure transactions the * PCI-E controller does not check the device number bits and just * assumes that the device number bits are 0.
*/ if (bus->number == hose->first_busno ||
bus->primary == hose->first_busno) { if (devfn & 0xf8) return PCIBIOS_DEVICE_NOT_FOUND;
}
if (ppc_md.pci_exclude_device) { if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) return PCIBIOS_DEVICE_NOT_FOUND;
}
if (of_address_to_resource(dev, 1, &rsrc_cfg)) {
printk(KERN_WARNING "No pci config register base in dev tree, " "using default\n"); /* * MPC83xx supports up to two host controllers * one at 0x8500 has config space registers at 0x8300 * one at 0x8600 has config space registers at 0x8380
*/ if ((rsrc_reg.start & 0xfffff) == 0x8500)
rsrc_cfg.start = (rsrc_reg.start & 0xfff00000) + 0x8300; elseif ((rsrc_reg.start & 0xfffff) == 0x8600)
rsrc_cfg.start = (rsrc_reg.start & 0xfff00000) + 0x8380;
} /* * Controller at offset 0x8500 is primary
*/ if ((rsrc_reg.start & 0xfffff) == 0x8500)
primary = 1; else
primary = 0;
/* Get bus range if any */
bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %pOF, assume" " bus 0\n", dev);
}
pci_add_flags(PCI_REASSIGN_ALL_BUS);
hose = pcibios_alloc_controller(dev); if (!hose) return -ENOMEM;
u64 fsl_pci_immrbar_base(struct pci_controller *hose)
{ #ifdef CONFIG_PPC_83xx if (is_mpc83xx_pci) { struct mpc83xx_pcie_priv *pcie = hose->dn->data; struct pex_inbound_window *in; int i;
/* Walk the Root Complex Inbound windows to match IMMR base */
in = pcie->cfg_type0 + PEX_RC_INWIN_BASE; for (i = 0; i < 4; i++) { /* not enabled, skip */ if (!(in_le32(&in[i].ar) & PEX_RCIWARn_EN)) continue;
/* * For PEXCSRBAR, bit 3-0 indicate prefetchable and * address type. So when getting base address, these * bits should be masked
*/
base &= PCI_BASE_ADDRESS_MEM_MASK;
if (is_in_pci_mem_space(addr)) { if (user_mode(regs))
ret = copy_from_user_nofault(&inst,
(void __user *)regs->nip, sizeof(inst)); else
ret = get_kernel_nofault(inst, (void *)regs->nip);
/* * The following entries are for compatibility with older device * trees.
*/
{ .compatible = "fsl,p1022-pcie", },
{ .compatible = "fsl,p4080-pcie", },
/* Callers can specify the primary bus using other means. */ if (fsl_pci_primary) return;
/* If a PCI host bridge contains an ISA node, it's primary. */
np = of_find_node_by_type(NULL, "isa"); while ((fsl_pci_primary = of_get_parent(np))) {
of_node_put(np);
np = fsl_pci_primary;
if (of_match_node(pci_ids, np) && of_device_is_available(np)) return;
}
/* * If there's no PCI host bridge with ISA then check for * PCI host bridge with alias "pci0" (first PCI host bridge).
*/
np = of_find_node_by_path("pci0"); if (np && of_match_node(pci_ids, np) && of_device_is_available(np)) {
fsl_pci_primary = np;
of_node_put(np); return;
} if (np)
of_node_put(np);
/* * If there's no PCI host bridge with ISA, arbitrarily * designate one as primary. This can go away once * various bugs with primary-less systems are fixed.
*/
for_each_matching_node(np, pci_ids) { if (of_device_is_available(np)) {
fsl_pci_primary = np; return;
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.