diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_sabre.c')
-rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 340 |
1 files changed, 62 insertions, 278 deletions
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index bbf624517508..f4e346092a53 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -254,9 +254,6 @@ static int __sabre_out_of_range(struct pci_pbm_info *pbm, return 0; return ((pbm->parent == 0) || - ((pbm == &pbm->parent->pbm_B) && - (bus == pbm->pci_first_busno) && - PCI_SLOT(devfn) > 8) || ((pbm == &pbm->parent->pbm_A) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 8)); @@ -800,12 +797,10 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { sabre_check_iommu_error(p, afsr, afar); pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus); - pci_scan_for_target_abort(p, &p->pbm_B, p->pbm_B.pci_bus); } - if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) { + if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus); - pci_scan_for_master_abort(p, &p->pbm_B, p->pbm_B.pci_bus); - } + /* For excessive retries, SABRE/PBM will abort the device * and there is no way to specifically check for excessive * retries in the config space status registers. So what @@ -813,10 +808,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) * abort events. */ - if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) { + if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus); - pci_scan_for_parity_error(p, &p->pbm_B, p->pbm_B.pci_bus); - } return IRQ_HANDLED; } @@ -935,44 +928,33 @@ static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) struct pci_dev *pdev; list_for_each_entry(pdev, &sabre_bus->devices, bus_list) { - if (pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_SIMBA) { - u32 word32; u16 word16; - sabre_read_pci_cfg(pdev->bus, pdev->devfn, - PCI_COMMAND, 2, &word32); - word16 = (u16) word32; + pci_read_config_word(pdev, PCI_COMMAND, &word16); word16 |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; - word32 = (u32) word16; - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_COMMAND, 2, word32); + pci_write_config_word(pdev, PCI_COMMAND, word16); /* Status register bits are "write 1 to clear". */ - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_STATUS, 2, 0xffff); - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_SEC_STATUS, 2, 0xffff); + pci_write_config_word(pdev, PCI_STATUS, 0xffff); + pci_write_config_word(pdev, PCI_SEC_STATUS, 0xffff); /* Use a primary/seconday latency timer value * of 64. */ - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_LATENCY_TIMER, 1, 64); - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_SEC_LATENCY_TIMER, 1, 64); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); + pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64); /* Enable reporting/forwarding of master aborts, * parity, and SERR. */ - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_BRIDGE_CONTROL, 1, - (PCI_BRIDGE_CTL_PARITY | - PCI_BRIDGE_CTL_SERR | - PCI_BRIDGE_CTL_MASTER_ABORT)); + pci_write_config_byte(pdev, PCI_BRIDGE_CONTROL, + (PCI_BRIDGE_CTL_PARITY | + PCI_BRIDGE_CTL_SERR | + PCI_BRIDGE_CTL_MASTER_ABORT)); } } } @@ -980,16 +962,13 @@ static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) static void sabre_scan_bus(struct pci_controller_info *p) { static int once; - struct pci_bus *sabre_bus, *pbus; - struct pci_pbm_info *pbm; - int sabres_scanned; + struct pci_bus *pbus; /* The APB bridge speaks to the Sabre host PCI bridge * at 66Mhz, but the front side of APB runs at 33Mhz * for both segments. */ p->pbm_A.is_66mhz_capable = 0; - p->pbm_B.is_66mhz_capable = 0; /* This driver has not been verified to handle * multiple SABREs yet, so trap this. @@ -1003,36 +982,13 @@ static void sabre_scan_bus(struct pci_controller_info *p) } once++; - sabre_bus = pci_scan_one_pbm(&p->pbm_A); - if (!sabre_bus) + pbus = pci_scan_one_pbm(&p->pbm_A); + if (!pbus) return; - sabre_root_bus = sabre_bus; - - apb_init(p, sabre_bus); - - sabres_scanned = 0; + sabre_root_bus = pbus; - list_for_each_entry(pbus, &sabre_bus->children, node) { - - if (pbus->number == p->pbm_A.pci_first_busno) { - pbm = &p->pbm_A; - } else if (pbus->number == p->pbm_B.pci_first_busno) { - pbm = &p->pbm_B; - } else - continue; - - sabres_scanned++; - pbus->sysdata = pbm; - pbm->pci_bus = pbus; - } - - if (!sabres_scanned) { - /* Hummingbird, no APBs. */ - pbm = &p->pbm_A; - sabre_bus->sysdata = pbm; - pbm->pci_bus = sabre_bus; - } + apb_init(p, pbus); sabre_register_error_handlers(p); } @@ -1089,213 +1045,54 @@ static void sabre_iommu_init(struct pci_controller_info *p, sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); } -static void pbm_register_toplevel_resources(struct pci_controller_info *p, - struct pci_pbm_info *pbm) +static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end) { - char *name = pbm->name; - unsigned long ibase = p->pbm_A.controller_regs + SABRE_IOSPACE; - unsigned long mbase = p->pbm_A.controller_regs + SABRE_MEMSPACE; - unsigned int devfn; - unsigned long first, last, i; - u8 *addr, map; - - sprintf(name, "SABRE%d PBM%c", - p->index, - (pbm == &p->pbm_A ? 'A' : 'B')); - pbm->io_space.name = pbm->mem_space.name = name; - - devfn = PCI_DEVFN(1, (pbm == &p->pbm_A) ? 0 : 1); - addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_IO_ADDRESS_MAP); - map = 0; - pci_config_read8(addr, &map); - - first = 8; - last = 0; - for (i = 0; i < 8; i++) { - if ((map & (1 << i)) != 0) { - if (first > i) - first = i; - if (last < i) - last = i; - } - } - pbm->io_space.start = ibase + (first << 21UL); - pbm->io_space.end = ibase + (last << 21UL) + ((1 << 21UL) - 1); + struct pci_pbm_info *pbm; + struct resource *rp; + + pbm = &p->pbm_A; + pbm->name = dp->full_name; + printk("%s: SABRE PCI Bus Module\n", pbm->name); + + pbm->chip_type = PBM_CHIP_TYPE_SABRE; + pbm->parent = p; + pbm->prom_node = dp; + pbm->pci_first_slot = 1; + pbm->pci_first_busno = p->pci_first_busno; + pbm->pci_last_busno = p->pci_last_busno; + + pbm->io_space.name = pbm->mem_space.name = pbm->name; + + pbm->io_space.start = p->pbm_A.controller_regs + SABRE_IOSPACE; + pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; pbm->io_space.flags = IORESOURCE_IO; - addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_MEM_ADDRESS_MAP); - map = 0; - pci_config_read8(addr, &map); - - first = 8; - last = 0; - for (i = 0; i < 8; i++) { - if ((map & (1 << i)) != 0) { - if (first > i) - first = i; - if (last < i) - last = i; - } - } - pbm->mem_space.start = mbase + (first << 29UL); - pbm->mem_space.end = mbase + (last << 29UL) + ((1 << 29UL) - 1); + pbm->mem_space.start = (p->pbm_A.controller_regs + SABRE_MEMSPACE); + pbm->mem_space.end = (pbm->mem_space.start + ((1UL << 32UL) - 1UL)); pbm->mem_space.flags = IORESOURCE_MEM; if (request_resource(&ioport_resource, &pbm->io_space) < 0) { - prom_printf("Cannot register PBM-%c's IO space.\n", - (pbm == &p->pbm_A ? 'A' : 'B')); + prom_printf("Cannot register Sabre's IO space.\n"); prom_halt(); } if (request_resource(&iomem_resource, &pbm->mem_space) < 0) { - prom_printf("Cannot register PBM-%c's MEM space.\n", - (pbm == &p->pbm_A ? 'A' : 'B')); + prom_printf("Cannot register Sabre's MEM space.\n"); prom_halt(); } - /* Register legacy regions if this PBM covers that area. */ - if (pbm->io_space.start == ibase && - pbm->mem_space.start == mbase) - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); -} - -static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end) -{ - struct pci_pbm_info *pbm; - struct device_node *node; - struct property *prop; - u32 *busrange; - int len, simbas_found; - - simbas_found = 0; - node = dp->child; - while (node != NULL) { - if (strcmp(node->name, "pci")) - goto next_pci; - - prop = of_find_property(node, "model", NULL); - if (!prop || strncmp(prop->value, "SUNW,simba", prop->length)) - goto next_pci; - - simbas_found++; - - prop = of_find_property(node, "bus-range", NULL); - busrange = prop->value; - if (busrange[0] == 1) - pbm = &p->pbm_B; - else - pbm = &p->pbm_A; - - pbm->name = node->full_name; - printk("%s: SABRE PCI Bus Module\n", pbm->name); - - pbm->chip_type = PBM_CHIP_TYPE_SABRE; - pbm->parent = p; - pbm->prom_node = node; - pbm->pci_first_slot = 1; - pbm->pci_first_busno = busrange[0]; - pbm->pci_last_busno = busrange[1]; - - prop = of_find_property(node, "ranges", &len); - if (prop) { - pbm->pbm_ranges = prop->value; - pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); - } else { - pbm->num_pbm_ranges = 0; - } - - prop = of_find_property(node, "interrupt-map", &len); - if (prop) { - pbm->pbm_intmap = prop->value; - pbm->num_pbm_intmap = - (len / sizeof(struct linux_prom_pci_intmap)); - - prop = of_find_property(node, "interrupt-map-mask", - NULL); - pbm->pbm_intmask = prop->value; - } else { - pbm->num_pbm_intmap = 0; - } - - pbm_register_toplevel_resources(p, pbm); - - next_pci: - node = node->sibling; - } - if (simbas_found == 0) { - struct resource *rp; - - /* No APBs underneath, probably this is a hummingbird - * system. - */ - pbm = &p->pbm_A; - pbm->parent = p; - pbm->prom_node = dp; - pbm->pci_first_busno = p->pci_first_busno; - pbm->pci_last_busno = p->pci_last_busno; - - prop = of_find_property(dp, "ranges", &len); - if (prop) { - pbm->pbm_ranges = prop->value; - pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); - } else { - pbm->num_pbm_ranges = 0; - } - - prop = of_find_property(dp, "interrupt-map", &len); - if (prop) { - pbm->pbm_intmap = prop->value; - pbm->num_pbm_intmap = - (len / sizeof(struct linux_prom_pci_intmap)); - - prop = of_find_property(dp, "interrupt-map-mask", - NULL); - pbm->pbm_intmask = prop->value; - } else { - pbm->num_pbm_intmap = 0; - } - - pbm->name = dp->full_name; - printk("%s: SABRE PCI Bus Module\n", pbm->name); - - pbm->io_space.name = pbm->mem_space.name = pbm->name; - - /* Hack up top-level resources. */ - pbm->io_space.start = p->pbm_A.controller_regs + SABRE_IOSPACE; - pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; - pbm->io_space.flags = IORESOURCE_IO; - - pbm->mem_space.start = - (p->pbm_A.controller_regs + SABRE_MEMSPACE); - pbm->mem_space.end = - (pbm->mem_space.start + ((1UL << 32UL) - 1UL)); - pbm->mem_space.flags = IORESOURCE_MEM; - - if (request_resource(&ioport_resource, &pbm->io_space) < 0) { - prom_printf("Cannot register Hummingbird's IO space.\n"); - prom_halt(); - } - if (request_resource(&iomem_resource, &pbm->mem_space) < 0) { - prom_printf("Cannot register Hummingbird's MEM space.\n"); - prom_halt(); - } - - rp = kmalloc(sizeof(*rp), GFP_KERNEL); - if (!rp) { - prom_printf("Cannot allocate IOMMU resource.\n"); - prom_halt(); - } - rp->name = "IOMMU"; - rp->start = pbm->mem_space.start + (unsigned long) dma_start; - rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL; - rp->flags = IORESOURCE_BUSY; - request_resource(&pbm->mem_space, rp); - - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); + rp = kmalloc(sizeof(*rp), GFP_KERNEL); + if (!rp) { + prom_printf("Cannot allocate IOMMU resource.\n"); + prom_halt(); } + rp->name = "IOMMU"; + rp->start = pbm->mem_space.start + (unsigned long) dma_start; + rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL; + rp->flags = IORESOURCE_BUSY; + request_resource(&pbm->mem_space, rp); + + pci_register_legacy_regions(&pbm->io_space, + &pbm->mem_space); } void sabre_init(struct device_node *dp, char *model_name) @@ -1303,7 +1100,6 @@ void sabre_init(struct device_node *dp, char *model_name) struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; struct pci_iommu *iommu; - struct property *prop; int tsbsize; u32 *busrange; u32 *vdma; @@ -1314,13 +1110,9 @@ void sabre_init(struct device_node *dp, char *model_name) if (!strcmp(model_name, "pci108e,a001")) hummingbird_p = 1; else if (!strcmp(model_name, "SUNW,sabre")) { - prop = of_find_property(dp, "compatible", NULL); - if (prop) { - const char *compat = prop->value; - - if (!strcmp(compat, "pci108e,a001")) - hummingbird_p = 1; - } + const char *compat = of_get_property(dp, "compatible", NULL); + if (compat && !strcmp(compat, "pci108e,a001")) + hummingbird_p = 1; if (!hummingbird_p) { struct device_node *dp; @@ -1344,18 +1136,14 @@ void sabre_init(struct device_node *dp, char *model_name) prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n"); prom_halt(); } - p->pbm_A.iommu = p->pbm_B.iommu = iommu; + p->pbm_A.iommu = iommu; - upa_portid = 0xff; - prop = of_find_property(dp, "upa-portid", NULL); - if (prop) - upa_portid = *(u32 *) prop->value; + upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); p->next = pci_controller_root; pci_controller_root = p; p->pbm_A.portid = upa_portid; - p->pbm_B.portid = upa_portid; p->index = pci_num_controllers++; p->pbms_same_domain = 1; p->scan_bus = sabre_scan_bus; @@ -1367,14 +1155,12 @@ void sabre_init(struct device_node *dp, char *model_name) * Map in SABRE register set and report the presence of this SABRE. */ - prop = of_find_property(dp, "reg", NULL); - pr_regs = prop->value; + pr_regs = of_get_property(dp, "reg", NULL); /* * First REG in property is base of entire SABRE register space. */ p->pbm_A.controller_regs = pr_regs[0].phys_addr; - p->pbm_B.controller_regs = pr_regs[0].phys_addr; /* Clear interrupts */ @@ -1392,11 +1178,10 @@ void sabre_init(struct device_node *dp, char *model_name) SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); /* Now map in PCI config space for entire SABRE. */ - p->pbm_A.config_space = p->pbm_B.config_space = + p->pbm_A.config_space = (p->pbm_A.controller_regs + SABRE_CONFIGSPACE); - prop = of_find_property(dp, "virtual-dma", NULL); - vdma = prop->value; + vdma = of_get_property(dp, "virtual-dma", NULL); dma_mask = vdma[0]; switch(vdma[1]) { @@ -1420,8 +1205,7 @@ void sabre_init(struct device_node *dp, char *model_name) sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); - prop = of_find_property(dp, "bus-range", NULL); - busrange = prop->value; + busrange = of_get_property(dp, "bus-range", NULL); p->pci_first_busno = busrange[0]; p->pci_last_busno = busrange[1]; |