diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_schizo.c')
-rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 311 |
1 files changed, 60 insertions, 251 deletions
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index f16449ccd7b..5c6e2a9b91f 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -217,116 +217,6 @@ static struct pci_ops schizo_ops = { .write = schizo_write_pci_cfg, }; -/* SCHIZO interrupt mapping support. Unlike Psycho, for this controller the - * imap/iclr registers are per-PBM. - */ -#define SCHIZO_IMAP_BASE 0x1000UL -#define SCHIZO_ICLR_BASE 0x1400UL - -static unsigned long schizo_imap_offset(unsigned long ino) -{ - return SCHIZO_IMAP_BASE + (ino * 8UL); -} - -static unsigned long schizo_iclr_offset(unsigned long ino) -{ - return SCHIZO_ICLR_BASE + (ino * 8UL); -} - -static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2) -{ - unsigned long sync_reg = (unsigned long) _arg2; - u64 mask = 1UL << (ino & IMAP_INO); - u64 val; - int limit; - - schizo_write(sync_reg, mask); - - limit = 100000; - val = 0; - while (--limit) { - val = schizo_read(sync_reg); - if (!(val & mask)) - break; - } - if (limit <= 0) { - printk("tomatillo_wsync_handler: DMA won't sync [%lx:%lx]\n", - val, mask); - } - - if (_arg1) { - static unsigned char cacheline[64] - __attribute__ ((aligned (64))); - - __asm__ __volatile__("rd %%fprs, %0\n\t" - "or %0, %4, %1\n\t" - "wr %1, 0x0, %%fprs\n\t" - "stda %%f0, [%5] %6\n\t" - "wr %0, 0x0, %%fprs\n\t" - "membar #Sync" - : "=&r" (mask), "=&r" (val) - : "0" (mask), "1" (val), - "i" (FPRS_FEF), "r" (&cacheline[0]), - "i" (ASI_BLK_COMMIT_P)); - } -} - -static unsigned long schizo_ino_to_iclr(struct pci_pbm_info *pbm, - unsigned int ino) -{ - ino &= PCI_IRQ_INO; - return pbm->pbm_regs + schizo_iclr_offset(ino) + 4; -} - -static unsigned long schizo_ino_to_imap(struct pci_pbm_info *pbm, - unsigned int ino) -{ - ino &= PCI_IRQ_INO; - return pbm->pbm_regs + schizo_imap_offset(ino) + 4; -} - -static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, - struct pci_dev *pdev, - unsigned int ino) -{ - unsigned long imap, iclr; - int ign_fixup; - int virt_irq; - - ino &= PCI_IRQ_INO; - - /* Now build the IRQ bucket. */ - imap = schizo_ino_to_imap(pbm, ino); - iclr = schizo_ino_to_iclr(pbm, ino); - - /* On Schizo, no inofixup occurs. This is because each - * INO has it's own IMAP register. On Psycho and Sabre - * there is only one IMAP register for each PCI slot even - * though four different INOs can be generated by each - * PCI slot. - * - * But, for JBUS variants (essentially, Tomatillo), we have - * to fixup the lowest bit of the interrupt group number. - */ - ign_fixup = 0; - if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { - if (pbm->portid & 1) - ign_fixup = (1 << 6); - } - - virt_irq = build_irq(ign_fixup, iclr, imap); - - if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { - irq_install_pre_handler(virt_irq, - tomatillo_wsync_handler, - ((pbm->chip_version <= 4) ? - (void *) 1 : (void *) 0), - (void *) pbm->sync_reg); - } - - return virt_irq; -} - /* SCHIZO error handling support. */ enum schizo_error_type { UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR @@ -362,34 +252,6 @@ struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino) return &p->pbm_A; } -static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) -{ - struct pci_pbm_info *pbm; - unsigned long iclr; - - /* Do not clear the interrupt for the other PCI bus. - * - * This "ACK both PBM IRQs" only needs to be performed - * for chip-wide error interrupts. - */ - if ((irq & IMAP_INO) == SCHIZO_PCIERR_A_INO || - (irq & IMAP_INO) == SCHIZO_PCIERR_B_INO) - return; - - pbm = pbm_for_ino(p, irq); - if (pbm == &p->pbm_A) - pbm = &p->pbm_B; - else - pbm = &p->pbm_A; - - schizo_irq_build(pbm, NULL, - (pbm->portid << 6) | (irq & IMAP_INO)); - - iclr = schizo_ino_to_iclr(pbm, - (pbm->portid << 6) | (irq & IMAP_INO)); - upa_writel(ICLR_IDLE, iclr); -} - #define SCHIZO_STC_ERR 0xb800UL /* --> 0xba00 */ #define SCHIZO_STC_TAG 0xba00UL /* --> 0xba80 */ #define SCHIZO_STC_LINE 0xbb00UL /* --> 0xbb80 */ @@ -720,8 +582,6 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs) /* Interrogate IOMMU for error status. */ schizo_check_iommu_error(p, UE_ERR); - schizo_clear_other_err_intr(p, irq); - return IRQ_HANDLED; } @@ -811,8 +671,6 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs) printk("(none)"); printk("]\n"); - schizo_clear_other_err_intr(p, irq); - return IRQ_HANDLED; } @@ -1033,8 +891,6 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg if (error_bits & (SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_SPERR)) pci_scan_for_parity_error(p, pbm, pbm->pci_bus); - schizo_clear_other_err_intr(p, irq); - return IRQ_HANDLED; } @@ -1090,7 +946,6 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs * printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", p->index, errlog); - schizo_clear_other_err_intr(p, irq); return IRQ_HANDLED; } @@ -1098,7 +953,6 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs * p->index); schizo_check_iommu_error(p, SAFARI_ERR); - schizo_clear_other_err_intr(p, irq); return IRQ_HANDLED; } @@ -1130,74 +984,47 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs * static void tomatillo_register_error_handlers(struct pci_controller_info *p) { struct pci_pbm_info *pbm; - unsigned int irq; + struct of_device *op; u64 tmp, err_mask, err_no_mask; - /* Build IRQs and register handlers. */ + /* Tomatillo IRQ property layout is: + * 0: PCIERR + * 1: UE ERR + * 2: CE ERR + * 3: SERR + * 4: POWER FAIL? + */ + pbm = pbm_for_ino(p, SCHIZO_UE_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_UE_INO); - if (request_irq(irq, schizo_ue_intr, - SA_SHIRQ, "TOMATILLO UE", p) < 0) { - prom_printf("%s: Cannot register UE interrupt.\n", - pbm->name); - prom_halt(); - } - tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO)); - upa_writel(tmp, (pbm->pbm_regs + - schizo_imap_offset(SCHIZO_UE_INO) + 4)); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[1], schizo_ue_intr, SA_SHIRQ, + "TOMATILLO_UE", p); pbm = pbm_for_ino(p, SCHIZO_CE_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_CE_INO); - if (request_irq(irq, schizo_ce_intr, - SA_SHIRQ, "TOMATILLO CE", p) < 0) { - prom_printf("%s: Cannot register CE interrupt.\n", - pbm->name); - prom_halt(); - } - tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO)); - upa_writel(tmp, (pbm->pbm_regs + - schizo_imap_offset(SCHIZO_CE_INO) + 4)); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[2], schizo_ce_intr, SA_SHIRQ, + "TOMATILLO CE", p); pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); - irq = schizo_irq_build(pbm, NULL, ((pbm->portid << 6) | - SCHIZO_PCIERR_A_INO)); - if (request_irq(irq, schizo_pcierr_intr, - SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) { - prom_printf("%s: Cannot register PBM A PciERR interrupt.\n", - pbm->name); - prom_halt(); - } - tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | - SCHIZO_PCIERR_A_INO))); - upa_writel(tmp, (pbm->pbm_regs + - schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[0], schizo_pcierr_intr, SA_SHIRQ, + "TOMATILLO PCIERR-A", pbm); + pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); - irq = schizo_irq_build(pbm, NULL, ((pbm->portid << 6) | - SCHIZO_PCIERR_B_INO)); - if (request_irq(irq, schizo_pcierr_intr, - SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) { - prom_printf("%s: Cannot register PBM B PciERR interrupt.\n", - pbm->name); - prom_halt(); - } - tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | - SCHIZO_PCIERR_B_INO))); - upa_writel(tmp, (pbm->pbm_regs + - schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[0], schizo_pcierr_intr, SA_SHIRQ, + "TOMATILLO PCIERR-B", pbm); pbm = pbm_for_ino(p, SCHIZO_SERR_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_SERR_INO); - if (request_irq(irq, schizo_safarierr_intr, - SA_SHIRQ, "TOMATILLO SERR", p) < 0) { - prom_printf("%s: Cannot register SafariERR interrupt.\n", - pbm->name); - prom_halt(); - } - tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | - SCHIZO_SERR_INO))); - upa_writel(tmp, (pbm->pbm_regs + - schizo_imap_offset(SCHIZO_SERR_INO) + 4)); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[3], schizo_safarierr_intr, SA_SHIRQ, + "TOMATILLO SERR", p); /* Enable UE and CE interrupts for controller. */ schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL, @@ -1265,64 +1092,47 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) static void schizo_register_error_handlers(struct pci_controller_info *p) { struct pci_pbm_info *pbm; - unsigned int irq; + struct of_device *op; u64 tmp, err_mask, err_no_mask; - /* Build IRQs and register handlers. */ + /* Schizo IRQ property layout is: + * 0: PCIERR + * 1: UE ERR + * 2: CE ERR + * 3: SERR + * 4: POWER FAIL? + */ + pbm = pbm_for_ino(p, SCHIZO_UE_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_UE_INO); - if (request_irq(irq, schizo_ue_intr, - SA_SHIRQ, "SCHIZO UE", p) < 0) { - prom_printf("%s: Cannot register UE interrupt.\n", - pbm->name); - prom_halt(); - } - tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO)); - upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[1], schizo_ue_intr, SA_SHIRQ, + "SCHIZO_UE", p); pbm = pbm_for_ino(p, SCHIZO_CE_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_CE_INO); - if (request_irq(irq, schizo_ce_intr, - SA_SHIRQ, "SCHIZO CE", p) < 0) { - prom_printf("%s: Cannot register CE interrupt.\n", - pbm->name); - prom_halt(); - } - tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO)); - upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4)); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[2], schizo_ce_intr, SA_SHIRQ, + "SCHIZO CE", p); pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO); - if (request_irq(irq, schizo_pcierr_intr, - SA_SHIRQ, "SCHIZO PCIERR", pbm) < 0) { - prom_printf("%s: Cannot register PBM A PciERR interrupt.\n", - pbm->name); - prom_halt(); - } - tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO)); - upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[0], schizo_pcierr_intr, SA_SHIRQ, + "SCHIZO PCIERR-A", pbm); + pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO); - if (request_irq(irq, schizo_pcierr_intr, - SA_SHIRQ, "SCHIZO PCIERR", &p->pbm_B) < 0) { - prom_printf("%s: Cannot register PBM B PciERR interrupt.\n", - pbm->name); - prom_halt(); - } - tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO)); - upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[0], schizo_pcierr_intr, SA_SHIRQ, + "SCHIZO PCIERR-B", pbm); pbm = pbm_for_ino(p, SCHIZO_SERR_INO); - irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_SERR_INO); - if (request_irq(irq, schizo_safarierr_intr, - SA_SHIRQ, "SCHIZO SERR", p) < 0) { - prom_printf("%s: Cannot register SafariERR interrupt.\n", - pbm->name); - prom_halt(); - } - tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_SERR_INO)); - upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4)); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[3], schizo_safarierr_intr, SA_SHIRQ, + "SCHIZO SERR", p); /* Enable UE and CE interrupts for controller. */ schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL, @@ -2022,7 +1832,6 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ p->scan_bus = (chip_type == PBM_CHIP_TYPE_TOMATILLO ? tomatillo_scan_bus : schizo_scan_bus); - p->irq_build = schizo_irq_build; p->base_address_update = schizo_base_address_update; p->resource_adjust = schizo_resource_adjust; p->pci_ops = &schizo_ops; |