[SPARC64]: SUN4U PCI-E controller support.

Some minor refactoring in the generic code was necessary for
this:

1) This controller requires 8-byte access to the interrupt map
   and clear register.  They are 64-bits on all the other
   SBUS and PCI controllers anyways, so this was easy to cure.

2) The IMAP register has a different layout and some bits that we
   need to preserve, so use a read/modify/write when making
   changes to the IMAP register in generic code.

3) Flushing the entire IOMMU TLB is best done with a single write
   to a register on this PCI controller, add a iommu->iommu_flushinv
   for this.

Still lacks MSI support, that will come later.

Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 6241e3d..3edc18e 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -279,7 +279,7 @@
 	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
 
 	if (likely(data)) {
-		unsigned long cpuid, imap;
+		unsigned long cpuid, imap, val;
 		unsigned int tid;
 
 		cpuid = irq_choose_cpu(virt_irq);
@@ -287,7 +287,11 @@
 
 		tid = sun4u_compute_tid(imap, cpuid);
 
-		upa_writel(tid | IMAP_VALID, imap);
+		val = upa_readq(imap);
+		val &= ~(IMAP_TID_UPA | IMAP_TID_JBUS |
+			 IMAP_AID_SAFARI | IMAP_NID_SAFARI);
+		val |= tid | IMAP_VALID;
+		upa_writeq(val, imap);
 	}
 }
 
@@ -297,10 +301,10 @@
 
 	if (likely(data)) {
 		unsigned long imap = data->imap;
-		u32 tmp = upa_readl(imap);
+		u32 tmp = upa_readq(imap);
 
 		tmp &= ~IMAP_VALID;
-		upa_writel(tmp, imap);
+		upa_writeq(tmp, imap);
 	}
 }
 
@@ -309,7 +313,7 @@
 	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
 
 	if (likely(data))
-		upa_writel(ICLR_IDLE, data->iclr);
+		upa_writeq(ICLR_IDLE, data->iclr);
 }
 
 static void sun4v_irq_enable(unsigned int virt_irq)
@@ -465,7 +469,7 @@
 
 	BUG_ON(tlb_type == hypervisor);
 
-	ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
+	ino = (upa_readq(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
 	bucket = &ivector_table[ino];
 	if (!bucket->virt_irq) {
 		bucket->virt_irq = virt_irq_alloc(__irq(bucket));