/* Probe a 32bit value on the bus and catch bus exceptions. * Returns nonzero on a bus exception.
* This is MIPS specific */ #define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr)))
/* Issue config commands only when the data link is up (at least * one external pcie device is present).
*/ if (dev >= 2 || !(bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_LSREG)
& BCMA_CORE_PCI_DLLP_LSREG_LINKUP)) goto out;
/* Type 0 transaction */ /* Slide the PCI window to the appropriate slot */
pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0); /* Calculate the address */
addr = pc->host_controller->host_cfg_addr;
addr |= (dev << BCMA_CORE_PCI_CFG_SLOT_SHIFT);
addr |= (func << BCMA_CORE_PCI_CFG_FUN_SHIFT);
addr |= (off & ~3);
WARN_ON(!pc->hostmode); if (unlikely(len != 1 && len != 2 && len != 4)) goto out; if (dev == 0) { /* we support only two functions on device 0 */ if (func > 1) goto out;
WARN_ON(!pc->hostmode); if (unlikely(len != 1 && len != 2 && len != 4)) goto out; if (dev == 0) { /* we support only two functions on device 0 */ if (func > 1) goto out;
/* return cap_offset if requested capability exists in the PCI config space */ static u8 bcma_find_pci_capability(struct bcma_drv_pci *pc, unsignedint dev, unsignedint func, u8 req_cap_id, unsignedchar *buf, u32 *buflen)
{
u8 cap_id;
u8 cap_ptr = 0;
u32 bufsize;
u8 byte_val;
/* check for Header type 0 */
bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, sizeof(u8)); if ((byte_val & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_NORMAL) return cap_ptr;
/* check if the capability pointer field exists */
bcma_extpci_read_config(pc, dev, func, PCI_STATUS, &byte_val, sizeof(u8)); if (!(byte_val & PCI_STATUS_CAP_LIST)) return cap_ptr;
/* check if the capability pointer is 0x00 */
bcma_extpci_read_config(pc, dev, func, PCI_CAPABILITY_LIST, &cap_ptr, sizeof(u8)); if (cap_ptr == 0x00) return cap_ptr;
/* loop through the capability list and see if the requested capability
* exists */
bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, sizeof(u8)); while (cap_id != req_cap_id) {
bcma_extpci_read_config(pc, dev, func, cap_ptr + 1, &cap_ptr, sizeof(u8)); if (cap_ptr == 0x00) return cap_ptr;
bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, sizeof(u8));
}
/* found the caller requested capability */ if ((buf != NULL) && (buflen != NULL)) {
u8 cap_data;
bufsize = *buflen; if (!bufsize) return cap_ptr;
*buflen = 0;
/* copy the capability data excluding cap ID and next ptr */
cap_data = cap_ptr + 2; if ((bufsize + cap_data) > PCI_CONFIG_SPACE_SIZE)
bufsize = PCI_CONFIG_SPACE_SIZE - cap_data;
*buflen = bufsize; while (bufsize--) {
bcma_extpci_read_config(pc, dev, func, cap_data, buf, sizeof(u8));
cap_data++;
buf++;
}
}
return cap_ptr;
}
/* If the root port is capable of returning Config Request * Retry Status (RRS) Completion Status to software then * enable the feature.
*/ staticvoid bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
{ struct bcma_bus *bus = pc->core->bus;
u8 cap_ptr, root_ctrl, root_cap, dev;
u16 val16; int i;
/* Initiate a configuration request to read the vendor id * field of the device function's config space header after * 100 ms wait time from the end of Reset. If the device is * not done with its internal initialization, it must at * least return a completion TLP, with a completion status * of "Configuration Request Retry Status (RRS)". The root * complex must complete the request to the host by returning * a read-data value of 0001h for the Vendor ID field and * all 1s for any additional bytes included in the request. * Poll using the config reads for max wait time of 1 sec or * until we receive the successful completion status. Repeat * the procedure for all the devices.
*/ for (dev = 1; dev < BCMA_PCI_SLOT_MAX; dev++) { for (i = 0; i < 100000; i++) {
bcma_extpci_read_config(pc, dev, 0,
PCI_VENDOR_ID, &val16, sizeof(val16)); if (val16 != 0x1) break;
udelay(10);
} if (val16 == 0x1)
bcma_err(bus, "PCI: Broken device in slot %d\n",
dev);
}
}
}
/* As per PCI Express Base Spec 1.1 we need to wait for * at least 100 ms from the end of a reset (cold/warm/hot) * before issuing configuration requests to PCI Express * devices.
*/
msleep(100);
/* Ok, ready to run, register it to the system. * The following needs change, if we want to port hostmode
* to non-MIPS platform. */
io_map_base = (unsignedlong)ioremap(pc_host->mem_resource.start,
resource_size(&pc_host->mem_resource));
pc_host->pci_controller.io_map_base = io_map_base;
set_io_port_base(pc_host->pci_controller.io_map_base); /* Give some time to the PCI controller to configure itself with the new
* values. Not waiting at this point causes crashes of the machine. */
usleep_range(10000, 15000);
register_pci_controller(&pc_host->pci_controller); return;
}
/* Early PCI fixup for a device on the PCI-core bridge. */ staticvoid bcma_core_pci_fixup_pcibridge(struct pci_dev *dev)
{ if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { /* This is not a device on the PCI-core bridge. */ return;
} if (PCI_SLOT(dev->devfn) != 0) return;
pr_info("PCI: Fixing up bridge %s\n", pci_name(dev));
/* Enable PCI bridge bus mastering and memory space */
pci_set_master(dev); if (pcibios_enable_device(dev, ~0) < 0) {
pr_err("PCI: BCMA bridge enable failed\n"); return;
}
/* Early PCI fixup for all PCI-cores to set the correct memory address. */ staticvoid bcma_core_pci_fixup_addresses(struct pci_dev *dev)
{ struct resource *res; int pos, err;
if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { /* This is not a device on the PCI-core bridge. */ return;
} if (PCI_SLOT(dev->devfn) == 0) return;
pr_info("PCI: Fixing up addresses %s\n", pci_name(dev));
for (pos = 0; pos < 6; pos++) {
res = &dev->resource[pos]; if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) {
err = pci_assign_resource(dev, pos); if (err)
pr_err("PCI: Problem fixing up the addresses on %s\n",
pci_name(dev));
}
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses);
/* This function is called when doing a pci_enable_device().
* We must first check if the device is a device on the PCI-core bridge. */ int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
{ struct bcma_drv_pci_host *pc_host; int readrq;
if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { /* This is not a device on the PCI-core bridge. */ return -ENODEV;
}
pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
pci_ops);
pr_info("PCI: Fixing up device %s\n", pci_name(dev));
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.