static int indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { struct pci_controller *hose = pci_bus_to_host(bus); volatile void __iomem *cfg_data; u8 cfg_type = 0; u32 bus_no, reg; if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK) { if (bus->number != hose->first_busno) return PCIBIOS_DEVICE_NOT_FOUND; if (devfn != 0) 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 (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE) if (bus->number != hose->first_busno) cfg_type = 1; bus_no = (bus->number == hose->first_busno) ? hose->self_busno : bus->number; if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG) reg = ((offset & 0xf00) << 16) | (offset & 0xfc); else reg = offset & 0xfc; if (hose->indirect_type & PPC_INDIRECT_TYPE_BIG_ENDIAN) out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) | (devfn << 8) | reg | cfg_type)); else out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) | (devfn << 8) | reg | cfg_type)); /* suppress setting of PCI_PRIMARY_BUS */ if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS) if ((offset == PCI_PRIMARY_BUS) && (bus->number == hose->first_busno)) val &= 0xffffff00; /* Workaround for PCI_28 Errata in 440EPx/GRx */ if ((hose->indirect_type & PPC_INDIRECT_TYPE_BROKEN_MRM) && offset == PCI_CACHE_LINE_SIZE) { val = 0; } /* * Note: the caller has already checked that offset is * suitably aligned and that len is 1, 2 or 4. */ cfg_data = hose->cfg_data + (offset & 3); switch (len) { case 1: out_8(cfg_data, val); break; case 2: out_le16(cfg_data, val); break; default: out_le32(cfg_data, val); break; } return PCIBIOS_SUCCESSFUL; }
int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) { struct device_node *dn, *ppnode; struct pci_dev *ppdev; u32 lspec; u32 laddr[3]; u8 pin; int rc; /* Check if we have a device node, if yes, fallback to standard OF * parsing */ dn = pci_device_to_OF_node(pdev); if (dn) return of_irq_map_one(dn, 0, out_irq); /* Ok, we don't, time to have fun. Let's start by building up an * interrupt spec. we assume #interrupt-cells is 1, which is standard * for PCI. If you do different, then don't use that routine. */ rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); if (rc != 0) return rc; /* No pin, exit */ if (pin == 0) return -ENODEV; /* Now we walk up the PCI tree */ lspec = pin; for (;;) { /* Get the pci_dev of our parent */ ppdev = pdev->bus->self; /* Ouch, it's a host bridge... */ if (ppdev == NULL) { #ifdef CONFIG_PPC64 ppnode = pci_bus_to_OF_node(pdev->bus); #else struct pci_controller *host; host = pci_bus_to_host(pdev->bus); ppnode = host ? host->arch_data : NULL; #endif /* No node for host bridge ? give up */ if (ppnode == NULL) return -EINVAL; } else /* We found a P2P bridge, check if it has a node */ ppnode = pci_device_to_OF_node(ppdev); /* Ok, we have found a parent with a device-node, hand over to * the OF parsing code. * We build a unit address from the linux device to be used for * resolution. Note that we use the linux bus number which may * not match your firmware bus numbering. * Fortunately, in most cases, interrupt-map-mask doesn't include * the bus number as part of the matching. * You should still be careful about that though if you intend * to rely on this function (you ship a firmware that doesn't * create device nodes for all PCI devices). */ if (ppnode) break; /* We can only get here if we hit a P2P bridge with no node, * let's do standard swizzling and try again */ lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec); pdev = ppdev; } laddr[0] = (pdev->bus->number << 16) | (pdev->devfn << 8); laddr[1] = laddr[2] = 0; return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); }
static inline struct cxl_afu *pci_bus_to_afu(struct pci_bus *bus) { struct pci_controller *phb = bus ? pci_bus_to_host(bus) : NULL; return phb ? phb->private_data : NULL; }