📄 pci.c
字号:
* Note: the caller has already checked that offset is * suitably aligned and that len is 1, 2 or 4. */ switch (len) { case 1: out_8(addr, val); break; case 2: out_le16(addr, val); break; default: out_le32((u32 __iomem *)addr, val); break; } return PCIBIOS_SUCCESSFUL;}static struct pci_ops u3_ht_pci_ops ={ .read = u3_ht_read_config, .write = u3_ht_write_config,};#define U4_PCIE_CFA0(devfn, off) \ ((1 << ((unsigned int)PCI_SLOT(dev_fn))) \ | (((unsigned int)PCI_FUNC(dev_fn)) << 8) \ | ((((unsigned int)(off)) >> 8) << 28) \ | (((unsigned int)(off)) & 0xfcU))#define U4_PCIE_CFA1(bus, devfn, off) \ ((((unsigned int)(bus)) << 16) \ |(((unsigned int)(devfn)) << 8) \ | ((((unsigned int)(off)) >> 8) << 28) \ |(((unsigned int)(off)) & 0xfcU) \ |1UL)static volatile void __iomem *u4_pcie_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, int offset){ unsigned int caddr; if (bus == hose->first_busno) { caddr = U4_PCIE_CFA0(dev_fn, offset); } else caddr = U4_PCIE_CFA1(bus, dev_fn, offset); /* Uninorth will return garbage if we don't read back the value ! */ do { out_le32(hose->cfg_addr, caddr); } while (in_le32(hose->cfg_addr) != caddr); offset &= 0x03; return hose->cfg_data + offset;}static int u4_pcie_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val){ struct pci_controller *hose; volatile void __iomem *addr; hose = pci_bus_to_host(bus); if (hose == NULL) return PCIBIOS_DEVICE_NOT_FOUND; if (offset >= 0x1000) return PCIBIOS_BAD_REGISTER_NUMBER; addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset); if (!addr) return PCIBIOS_DEVICE_NOT_FOUND; /* * Note: the caller has already checked that offset is * suitably aligned and that len is 1, 2 or 4. */ switch (len) { case 1: *val = in_8(addr); break; case 2: *val = in_le16(addr); break; default: *val = in_le32(addr); break; } return PCIBIOS_SUCCESSFUL;}static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val){ struct pci_controller *hose; volatile void __iomem *addr; hose = pci_bus_to_host(bus); if (hose == NULL) return PCIBIOS_DEVICE_NOT_FOUND; if (offset >= 0x1000) return PCIBIOS_BAD_REGISTER_NUMBER; addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset); if (!addr) return PCIBIOS_DEVICE_NOT_FOUND; /* * Note: the caller has already checked that offset is * suitably aligned and that len is 1, 2 or 4. */ switch (len) { case 1: out_8(addr, val); break; case 2: out_le16(addr, val); break; default: out_le32(addr, val); break; } return PCIBIOS_SUCCESSFUL;}static struct pci_ops u4_pcie_pci_ops ={ .read = u4_pcie_read_config, .write = u4_pcie_write_config,};#endif /* CONFIG_PPC64 */#ifdef CONFIG_PPC32/* * For a bandit bridge, turn on cache coherency if necessary. * N.B. we could clean this up using the hose ops directly. */static void __init init_bandit(struct pci_controller *bp){ unsigned int vendev, magic; int rev; /* read the word at offset 0 in config space for device 11 */ out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID); udelay(2); vendev = in_le32(bp->cfg_data); if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) + PCI_VENDOR_ID_APPLE) { /* read the revision id */ out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID); udelay(2); rev = in_8(bp->cfg_data); if (rev != BANDIT_REVID) printk(KERN_WARNING "Unknown revision %d for bandit\n", rev); } else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) { printk(KERN_WARNING "bandit isn't? (%x)\n", vendev); return; } /* read the word at offset 0x50 */ out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC); udelay(2); magic = in_le32(bp->cfg_data); if ((magic & BANDIT_COHERENT) != 0) return; magic |= BANDIT_COHERENT; udelay(2); out_le32(bp->cfg_data, magic); printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n");}/* * Tweak the PCI-PCI bridge chip on the blue & white G3s. */static void __init init_p2pbridge(void){ struct device_node *p2pbridge; struct pci_controller* hose; u8 bus, devfn; u16 val; /* XXX it would be better here to identify the specific PCI-PCI bridge chip we have. */ p2pbridge = of_find_node_by_name(NULL, "pci-bridge"); if (p2pbridge == NULL || p2pbridge->parent == NULL || strcmp(p2pbridge->parent->name, "pci") != 0) goto done; if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) { DBG("Can't find PCI infos for PCI<->PCI bridge\n"); goto done; } /* Warning: At this point, we have not yet renumbered all busses. * So we must use OF walking to find out hose */ hose = pci_find_hose_for_OF_device(p2pbridge); if (!hose) { DBG("Can't find hose for PCI<->PCI bridge\n"); goto done; } if (early_read_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, &val) < 0) { printk(KERN_ERR "init_p2pbridge: couldn't read bridge" " control\n"); goto done; } val &= ~PCI_BRIDGE_CTL_MASTER_ABORT; early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);done: of_node_put(p2pbridge);}static void __init init_second_ohare(void){ struct device_node *np = of_find_node_by_name(NULL, "pci106b,7"); unsigned char bus, devfn; unsigned short cmd; if (np == NULL) return; /* This must run before we initialize the PICs since the second * ohare hosts a PIC that will be accessed there. */ if (pci_device_from_OF_node(np, &bus, &devfn) == 0) { struct pci_controller* hose = pci_find_hose_for_OF_device(np); if (!hose) { printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); return; } early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; cmd &= ~PCI_COMMAND_IO; early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); } has_second_ohare = 1;}/* * Some Apple desktop machines have a NEC PD720100A USB2 controller * on the motherboard. Open Firmware, on these, will disable the * EHCI part of it so it behaves like a pair of OHCI's. This fixup * code re-enables it ;) */static void __init fixup_nec_usb2(void){ struct device_node *nec; for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) { struct pci_controller *hose; u32 data; const u32 *prop; u8 bus, devfn; prop = of_get_property(nec, "vendor-id", NULL); if (prop == NULL) continue; if (0x1033 != *prop) continue; prop = of_get_property(nec, "device-id", NULL); if (prop == NULL) continue; if (0x0035 != *prop) continue; prop = of_get_property(nec, "reg", NULL); if (prop == NULL) continue; devfn = (prop[0] >> 8) & 0xff; bus = (prop[0] >> 16) & 0xff; if (PCI_FUNC(devfn) != 0) continue; hose = pci_find_hose_for_OF_device(nec); if (!hose) continue; early_read_config_dword(hose, bus, devfn, 0xe4, &data); if (data & 1UL) { printk("Found NEC PD720100A USB2 chip with disabled" " EHCI, fixing up...\n"); data &= ~1UL; early_write_config_dword(hose, bus, devfn, 0xe4, data); } }}static void __init setup_bandit(struct pci_controller *hose, struct resource *addr){ hose->ops = ¯isc_pci_ops; hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000); hose->cfg_data = ioremap(addr->start + 0xc00000, 0x1000); init_bandit(hose);}static int __init setup_uninorth(struct pci_controller *hose, struct resource *addr){ pci_assign_all_buses = 1; has_uninorth = 1; hose->ops = ¯isc_pci_ops; hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000); hose->cfg_data = ioremap(addr->start + 0xc00000, 0x1000); /* We "know" that the bridge at f2000000 has the PCI slots. */ return addr->start == 0xf2000000;}#endif /* CONFIG_PPC32 */#ifdef CONFIG_PPC64static void __init setup_u3_agp(struct pci_controller* hose){ /* On G5, we move AGP up to high bus number so we don't need * to reassign bus numbers for HT. If we ever have P2P bridges * on AGP, we'll have to move pci_assign_all_busses to the * pci_controller structure so we enable it for AGP and not for * HT childs. * We hard code the address because of the different size of * the reg address cell, we shall fix that by killing struct * reg_property and using some accessor functions instead */ hose->first_busno = 0xf0; hose->last_busno = 0xff; has_uninorth = 1; hose->ops = ¯isc_pci_ops; hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000); u3_agp = hose;}static void __init setup_u4_pcie(struct pci_controller* hose){ /* We currently only implement the "non-atomic" config space, to * be optimised later. */ hose->ops = &u4_pcie_pci_ops; hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000); /* The bus contains a bridge from root -> device, we need to * make it visible on bus 0 so that we pick the right type * of config cycles. If we didn't, we would have to force all * config cycles to be type 1. So we override the "bus-range" * property here */ hose->first_busno = 0x00; hose->last_busno = 0xff; u4_pcie = hose;}static void __init setup_u3_ht(struct pci_controller* hose){ struct device_node *np = (struct device_node *)hose->arch_data; struct pci_controller *other = NULL; int i, cur; hose->ops = &u3_ht_pci_ops; /* We hard code the address because of the different size of * the reg address cell, we shall fix that by killing struct * reg_property and using some accessor functions instead */ hose->cfg_data = ioremap(0xf2000000, 0x02000000); /* * /ht node doesn't expose a "ranges" property, so we "remove" * regions that have been allocated to AGP. So far, this version of * the code doesn't assign any of the 0xfxxxxxxx "fine" memory regions * to /ht. We need to fix that sooner or later by either parsing all * child "ranges" properties or figuring out the U3 address space * decoding logic and then read its configuration register (if any). */ hose->io_base_phys = 0xf4000000; hose->pci_io_size = 0x00400000; hose->io_resource.name = np->full_name; hose->io_resource.start = 0; hose->io_resource.end = 0x003fffff; hose->io_resource.flags = IORESOURCE_IO; hose->pci_mem_offset = 0; hose->first_busno = 0; hose->last_busno = 0xef; hose->mem_resources[0].name = np->full_name; hose->mem_resources[0].start = 0x80000000; hose->mem_resources[0].end = 0xefffffff; hose->mem_resources[0].flags = IORESOURCE_MEM; u3_ht = hose; if (u3_agp != NULL) other = u3_agp; else if (u4_pcie != NULL) other = u4_pcie; if (other == NULL) { DBG("U3/4 has no AGP/PCIE, using full resource range\n"); return; } /* Fixup bus range vs. PCIE */ if (u4_pcie) hose->last_busno = u4_pcie->first_busno - 1; /* We "remove" the AGP resources from the resources allocated to HT, * that is we create "holes". However, that code does assumptions * that so far happen to be true (cross fingers...), typically that * resources in the AGP node are properly ordered */ cur = 0; for (i=0; i<3; i++) { struct resource *res = &other->mem_resources[i]; if (res->flags != IORESOURCE_MEM) continue; /* We don't care about "fine" resources */ if (res->start >= 0xf0000000) continue; /* Check if it's just a matter of "shrinking" us in one * direction */ if (hose->mem_resources[cur].start == res->start) { DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n", cur, hose->mem_resources[cur].start, res->end + 1); hose->mem_resources[cur].start = res->end + 1; continue; } if (hose->mem_resources[cur].end == res->end) { DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n", cur, hose->mem_resources[cur].end, res->start - 1); hose->mem_resources[cur].end = res->start - 1; continue; } /* No, it's not the case, we need a hole */ if (cur == 2) { /* not enough resources for a hole, we drop part * of the range */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -