Merge ../linux-2.6-watchdog-mm
[linux-drm-fsl-dcu.git] / arch / sparc64 / kernel / pci_schizo.c
index f16449ccd7bc389d172509976e7171a3ca3c2125..66911b126aed65a723954c7d2b4e287938eff6b1 100644 (file)
@@ -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 */
@@ -653,7 +515,7 @@ static void schizo_check_iommu_error(struct pci_controller_info *p,
 #define SCHIZO_UEAFSR_MTAG     0x000000000000e000UL /* Safari */
 #define SCHIZO_UEAFSR_ECCSYND  0x00000000000001ffUL /* Safari */
 
-static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t schizo_ue_intr(int irq, void *dev_id)
 {
        struct pci_controller_info *p = dev_id;
        unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFSR;
@@ -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;
 }
 
@@ -743,7 +603,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
 #define SCHIZO_CEAFSR_MTAG     0x000000000000e000UL
 #define SCHIZO_CEAFSR_ECCSYND  0x00000000000001ffUL
 
-static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t schizo_ce_intr(int irq, void *dev_id)
 {
        struct pci_controller_info *p = dev_id;
        unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFSR;
@@ -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;
 }
 
@@ -920,7 +778,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm)
        return ret;
 }
 
-static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id)
 {
        struct pci_pbm_info *pbm = dev_id;
        struct pci_controller_info *p = pbm->parent;
@@ -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;
 }
 
@@ -1077,7 +933,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg
 /* We only expect UNMAP errors here.  The rest of the Safari errors
  * are marked fatal and thus cause a system reset.
  */
-static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id)
 {
        struct pci_controller_info *p = dev_id;
        u64 errlog;
@@ -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, IRQF_SHARED,
+                           "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, IRQF_SHARED,
+                           "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, IRQF_SHARED,
+                           "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, IRQF_SHARED,
+                           "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, IRQF_SHARED,
+                           "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, IRQF_SHARED,
+                           "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, IRQF_SHARED,
+                           "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, IRQF_SHARED,
+                           "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, IRQF_SHARED,
+                           "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, IRQF_SHARED,
+                           "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;