[SPARC64]: of_device layer IRQ resolution

Do IRQ determination generically by parsing the PROM properties,
and using IRQ controller drivers for final resolution.

One immediate positive effect is that all of the IRQ frobbing
in the EBUS, ISA, and PCI controller layers has been eliminated.
We just look up the of_device and use the properly computed
value.

The PCI controller irq_build() routines are gone and no longer
used.  Unfortunately sbus_build_irq() has to remain as there is
a direct reference to this in the sunzilog driver.  That can be
killed off once the sparc32 side of this is written and the
sunzilog driver is transformed into an "of" bus driver.

Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index f16449c..5c6e2a9 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -217,116 +217,6 @@
 	.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 @@
 	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 @@
 	/* 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 @@
 		printk("(none)");
 	printk("]\n");
 
-	schizo_clear_other_err_intr(p, irq);
-
 	return IRQ_HANDLED;
 }
 
@@ -1033,8 +891,6 @@
 	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 @@
 		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 @@
 	       p->index);
 	schizo_check_iommu_error(p, SAFARI_ERR);
 
-	schizo_clear_other_err_intr(p, irq);
 	return IRQ_HANDLED;
 }
 
@@ -1130,74 +984,47 @@
 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 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 @@
 	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;