return pci_controller_scan(pci_is_controller);
}
-struct pci_iommu_ops *pci_iommu_ops;
+const struct pci_iommu_ops *pci_iommu_ops;
EXPORT_SYMBOL(pci_iommu_ops);
-extern struct pci_iommu_ops pci_sun4u_iommu_ops,
+extern const struct pci_iommu_ops pci_sun4u_iommu_ops,
pci_sun4v_iommu_ops;
/* Find each controller in the system, attach and initialize
struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
struct device_node *node,
- struct pci_bus *bus, int devfn)
+ struct pci_bus *bus, int devfn,
+ int host_controller)
{
struct dev_archdata *sd;
struct pci_dev *dev;
if (type == NULL)
type = "";
- printk(" create device, devfn: %x, type: %s\n", devfn, type);
+ printk(" create device, devfn: %x, type: %s hostcontroller(%d)\n",
+ devfn, type, host_controller);
dev->bus = bus;
dev->sysdata = node;
dev->devfn = devfn;
dev->multifunction = 0; /* maybe a lie? */
- dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff);
- dev->device = of_getintprop_default(node, "device-id", 0xffff);
- dev->subsystem_vendor =
- of_getintprop_default(node, "subsystem-vendor-id", 0);
- dev->subsystem_device =
- of_getintprop_default(node, "subsystem-id", 0);
-
- dev->cfg_size = pci_cfg_space_size(dev);
-
- sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
- dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
- /* dev->class = of_getintprop_default(node, "class-code", 0); */
- /* We can't actually use the firmware value, we have to read what
- * is in the register right now. One reason is that in the case
- * of IDE interfaces the firmware can sample the value before the
- * the IDE interface is programmed into native mode.
- */
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
- dev->class = class >> 8;
+ if (host_controller) {
+ dev->vendor = 0x108e;
+ dev->device = 0x8000;
+ dev->subsystem_vendor = 0x0000;
+ dev->subsystem_device = 0x0000;
+ dev->cfg_size = 256;
+ dev->class = PCI_CLASS_BRIDGE_HOST << 8;
+ sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
+ 0x00, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ } else {
+ dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff);
+ dev->device = of_getintprop_default(node, "device-id", 0xffff);
+ dev->subsystem_vendor =
+ of_getintprop_default(node, "subsystem-vendor-id", 0);
+ dev->subsystem_device =
+ of_getintprop_default(node, "subsystem-id", 0);
+
+ dev->cfg_size = pci_cfg_space_size(dev);
+
+ /* We can't actually use the firmware value, we have
+ * to read what is in the register right now. One
+ * reason is that in the case of IDE interfaces the
+ * firmware can sample the value before the the IDE
+ * interface is programmed into native mode.
+ */
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
+ dev->class = class >> 8;
- printk(" class: 0x%x\n", dev->class);
+ sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
+ dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ }
+ printk(" class: 0x%x device name: %s\n",
+ dev->class, pci_name(dev));
dev->current_state = 4; /* unknown power state */
dev->error_state = pci_channel_io_normal;
- if (!strcmp(type, "pci") || !strcmp(type, "pciex")) {
- /* a PCI-PCI bridge */
+ if (host_controller) {
dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
dev->rom_base_reg = PCI_ROM_ADDRESS1;
- } else if (!strcmp(type, "cardbus")) {
- dev->hdr_type = PCI_HEADER_TYPE_CARDBUS;
+ dev->irq = PCI_IRQ_NONE;
} else {
- dev->hdr_type = PCI_HEADER_TYPE_NORMAL;
- dev->rom_base_reg = PCI_ROM_ADDRESS;
+ if (!strcmp(type, "pci") || !strcmp(type, "pciex")) {
+ /* a PCI-PCI bridge */
+ dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
+ dev->rom_base_reg = PCI_ROM_ADDRESS1;
+ } else if (!strcmp(type, "cardbus")) {
+ dev->hdr_type = PCI_HEADER_TYPE_CARDBUS;
+ } else {
+ dev->hdr_type = PCI_HEADER_TYPE_NORMAL;
+ dev->rom_base_reg = PCI_ROM_ADDRESS;
- dev->irq = sd->op->irqs[0];
- if (dev->irq == 0xffffffff)
- dev->irq = PCI_IRQ_NONE;
+ dev->irq = sd->op->irqs[0];
+ if (dev->irq == 0xffffffff)
+ dev->irq = PCI_IRQ_NONE;
+ }
}
-
pci_parse_of_addrs(sd->op, node, dev);
printk(" adding to system ...\n");
*last_p = last;
}
+static void __init pci_resource_adjust(struct resource *res,
+ struct resource *root)
+{
+ res->start += root->start;
+ res->end += root->start;
+}
+
/* Cook up fake bus resources for SUNW,simba PCI bridges which lack
* a proper 'ranges' property.
*/
res->start = (first << 21);
res->end = (last << 21) + ((1 << 21) - 1);
res->flags = IORESOURCE_IO;
- pbm->parent->resource_adjust(dev, res, &pbm->io_space);
+ pci_resource_adjust(res, &pbm->io_space);
pci_read_config_byte(dev, APB_MEM_ADDRESS_MAP, &map);
apb_calc_first_last(map, &first, &last);
res->start = (first << 21);
res->end = (last << 21) + ((1 << 21) - 1);
res->flags = IORESOURCE_MEM;
- pbm->parent->resource_adjust(dev, res, &pbm->mem_space);
+ pci_resource_adjust(res, &pbm->mem_space);
}
static void __init pci_of_scan_bus(struct pci_pbm_info *pbm,
ranges = of_get_property(node, "ranges", &len);
simba = 0;
if (ranges == NULL) {
- char *model = of_get_property(node, "model", NULL);
+ const char *model = of_get_property(node, "model", NULL);
if (model && !strcmp(model, "SUNW,simba")) {
simba = 1;
} else {
* layer routine that can calculate a resource for a given
* range property value in a PCI device.
*/
- pbm->parent->resource_adjust(dev, res, root);
+ pci_resource_adjust(res, root);
}
simba_cont:
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
devfn = (reg[0] >> 8) & 0xff;
/* create a new pci_dev for this device */
- dev = of_create_pci_dev(pbm, child, bus, devfn);
+ dev = of_create_pci_dev(pbm, child, bus, devfn, 0);
if (!dev)
continue;
printk("PCI: dev header type: %x\n", dev->hdr_type);
pci_bus_register_of_sysfs(child_bus);
}
+int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev,
+ unsigned int devfn,
+ int where, int size,
+ u32 *value)
+{
+ static u8 fake_pci_config[] = {
+ 0x8e, 0x10, /* Vendor: 0x108e (Sun) */
+ 0x00, 0x80, /* Device: 0x8000 (PBM) */
+ 0x46, 0x01, /* Command: 0x0146 (SERR, PARITY, MASTER, MEM) */
+ 0xa0, 0x22, /* Status: 0x02a0 (DEVSEL_MED, FB2B, 66MHZ) */
+ 0x00, 0x00, 0x00, 0x06, /* Class: 0x06000000 host bridge */
+ 0x00, /* Cacheline: 0x00 */
+ 0x40, /* Latency: 0x40 */
+ 0x00, /* Header-Type: 0x00 normal */
+ };
+
+ *value = 0;
+ if (where >= 0 && where < sizeof(fake_pci_config) &&
+ (where + size) >= 0 &&
+ (where + size) < sizeof(fake_pci_config) &&
+ size <= sizeof(u32)) {
+ while (size--) {
+ *value <<= 8;
+ *value |= fake_pci_config[where + size];
+ }
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
+ unsigned int devfn,
+ int where, int size,
+ u32 value)
+{
+ return PCIBIOS_SUCCESSFUL;
+}
+
struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm)
{
struct pci_controller_info *p = pbm->parent;
struct device_node *node = pbm->prom_node;
+ struct pci_dev *host_pdev;
struct pci_bus *bus;
printk("PCI: Scanning PBM %s\n", node->full_name);
bus->resource[0] = &pbm->io_space;
bus->resource[1] = &pbm->mem_space;
+ /* Create the dummy host bridge and link it in. */
+ host_pdev = of_create_pci_dev(pbm, node, bus, 0x00, 1);
+ bus->self = host_pdev;
+
pci_of_scan_bus(pbm, node, bus);
pci_bus_add_devices(bus);
pci_bus_register_of_sysfs(bus);
else
root = &pbm->mem_space;
- pbm->parent->resource_adjust(pdev, &zero_res, root);
+ pci_resource_adjust(&zero_res, root);
region->start = res->start - zero_res.start;
region->end = res->end - zero_res.start;
else
root = &pbm->mem_space;
- pbm->parent->resource_adjust(pdev, res, root);
+ pci_resource_adjust(res, root);
}
EXPORT_SYMBOL(pcibios_bus_to_resource);
unsigned long space_size, user_offset, user_size;
p = pbm->parent;
- if (p->pbms_same_domain) {
- unsigned long lowest, highest;
-
- lowest = ~0UL; highest = 0UL;
- if (mmap_state == pci_mmap_io) {
- if (p->pbm_A.io_space.flags) {
- lowest = p->pbm_A.io_space.start;
- highest = p->pbm_A.io_space.end + 1;
- }
- if (p->pbm_B.io_space.flags) {
- if (lowest > p->pbm_B.io_space.start)
- lowest = p->pbm_B.io_space.start;
- if (highest < p->pbm_B.io_space.end + 1)
- highest = p->pbm_B.io_space.end + 1;
- }
- space_size = highest - lowest;
- } else {
- if (p->pbm_A.mem_space.flags) {
- lowest = p->pbm_A.mem_space.start;
- highest = p->pbm_A.mem_space.end + 1;
- }
- if (p->pbm_B.mem_space.flags) {
- if (lowest > p->pbm_B.mem_space.start)
- lowest = p->pbm_B.mem_space.start;
- if (highest < p->pbm_B.mem_space.end + 1)
- highest = p->pbm_B.mem_space.end + 1;
- }
- space_size = highest - lowest;
- }
+ if (mmap_state == pci_mmap_io) {
+ space_size = (pbm->io_space.end -
+ pbm->io_space.start) + 1;
} else {
- if (mmap_state == pci_mmap_io) {
- space_size = (pbm->io_space.end -
- pbm->io_space.start) + 1;
- } else {
- space_size = (pbm->mem_space.end -
- pbm->mem_space.start) + 1;
- }
+ space_size = (pbm->mem_space.end -
+ pbm->mem_space.start) + 1;
}
/* Make sure the request is in range. */
(user_offset + user_size) > space_size)
return -EINVAL;
- if (p->pbms_same_domain) {
- unsigned long lowest = ~0UL;
-
- if (mmap_state == pci_mmap_io) {
- if (p->pbm_A.io_space.flags)
- lowest = p->pbm_A.io_space.start;
- if (p->pbm_B.io_space.flags &&
- lowest > p->pbm_B.io_space.start)
- lowest = p->pbm_B.io_space.start;
- } else {
- if (p->pbm_A.mem_space.flags)
- lowest = p->pbm_A.mem_space.start;
- if (p->pbm_B.mem_space.flags &&
- lowest > p->pbm_B.mem_space.start)
- lowest = p->pbm_B.mem_space.start;
- }
- vma->vm_pgoff = (lowest + user_offset) >> PAGE_SHIFT;
+ if (mmap_state == pci_mmap_io) {
+ vma->vm_pgoff = (pbm->io_space.start +
+ user_offset) >> PAGE_SHIFT;
} else {
- if (mmap_state == pci_mmap_io) {
- vma->vm_pgoff = (pbm->io_space.start +
- user_offset) >> PAGE_SHIFT;
- } else {
- vma->vm_pgoff = (pbm->mem_space.start +
- user_offset) >> PAGE_SHIFT;
- }
+ vma->vm_pgoff = (pbm->mem_space.start +
+ user_offset) >> PAGE_SHIFT;
}
return 0;
struct pci_controller_info *p = pbm->parent;
ret = p->index;
- if (p->pbms_same_domain == 0)
- ret = ((ret << 1) +
- ((pbm == &pbm->parent->pbm_B) ? 1 : 0));
+ ret = ((ret << 1) +
+ ((pbm == &pbm->parent->pbm_B) ? 1 : 0));
}
return ret;