[SBUS]: Start cleaning up generic sbus support layer.
David S. Miller [Tue, 20 Jun 2006 22:23:28 +0000 (15:23 -0700)]
In particular, move the IRQ probing out to sparc32/sparc64
arch specific code where it belongs.

Signed-off-by: David S. Miller <davem@davemloft.net>

arch/sparc/kernel/ioport.c
arch/sparc64/kernel/sbus.c
drivers/sbus/sbus.c
include/asm-sparc/sbus.h
include/asm-sparc64/sbus.h

index f9ff297..00cf411 100644 (file)
@@ -224,10 +224,54 @@ static void _sparc_free_io(struct resource *res)
 
 #ifdef CONFIG_SBUS
 
-void sbus_set_sbus64(struct sbus_dev *sdev, int x) {
+void sbus_set_sbus64(struct sbus_dev *sdev, int x)
+{
        printk("sbus_set_sbus64: unsupported\n");
 }
 
+extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
+void __init sbus_fill_device_irq(struct sbus_dev *sdev)
+{
+       struct linux_prom_irqs irqs[PROMINTR_MAX];
+       int len;
+
+       len = prom_getproperty(sdev->prom_node, "intr",
+                              (char *)irqs, sizeof(irqs));
+       if (len != -1) {
+               sdev->num_irqs = len / 8;
+               if (sdev->num_irqs == 0) {
+                       sdev->irqs[0] = 0;
+               } else if (sparc_cpu_model == sun4d) {
+                       for (len = 0; len < sdev->num_irqs; len++)
+                               sdev->irqs[len] =
+                                       sun4d_build_irq(sdev, irqs[len].pri);
+               } else {
+                       for (len = 0; len < sdev->num_irqs; len++)
+                               sdev->irqs[len] = irqs[len].pri;
+               }
+       } else {
+               int interrupts[PROMINTR_MAX];
+
+               /* No "intr" node found-- check for "interrupts" node.
+                * This node contains SBus interrupt levels, not IPLs
+                * as in "intr", and no vector values.  We convert
+                * SBus interrupt levels to PILs (platform specific).
+                */
+               len = prom_getproperty(sdev->prom_node, "interrupts",
+                                      (char *)interrupts, sizeof(interrupts));
+               if (len == -1) {
+                       sdev->irqs[0] = 0;
+                       sdev->num_irqs = 0;
+               } else {
+                       sdev->num_irqs = len / sizeof(int);
+                       for (len = 0; len < sdev->num_irqs; len++) {
+                               sdev->irqs[len] =
+                                       sbint_to_irq(sdev, interrupts[len]);
+                       }
+               }
+       } 
+}
+
 /*
  * Allocate a chunk of memory suitable for DMA.
  * Typically devices use them for control blocks.
index 8812417..8f7877a 100644 (file)
@@ -1225,3 +1225,24 @@ void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus)
 
        sysio_register_error_handlers(sbus);
 }
+
+void sbus_fill_device_irq(struct sbus_dev *sdev)
+{
+       struct linux_prom_irqs irqs[PROMINTR_MAX];
+       int len;
+
+       len = prom_getproperty(sdev->prom_node, "interrupts",
+                              (char *) irqs, sizeof(irqs));
+       if (len == -1 || len == 0) {
+               sdev->irqs[0] = 0;
+               sdev->num_irqs = 0;
+       } else {
+               unsigned int pri = irqs[0].pri;
+
+               sdev->num_irqs = 1;
+               if (pri < 0x20)
+                       pri += sdev->slot * 8;
+
+               sdev->irqs[0] = sbus_build_irq(sdev->bus, pri);
+       }
+}
index 5d30a3e..6e9b260 100644 (file)
@@ -1,7 +1,6 @@
-/* $Id: sbus.c,v 1.100 2002/01/24 15:36:24 davem Exp $
- * sbus.c:  SBus support routines.
+/* sbus.c: SBus support routines.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 2006 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/kernel.h>
 #include <asm/bpp.h>
 #include <asm/irq.h>
 
-struct sbus_bus *sbus_root = NULL;
-
-static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } };
-#ifdef CONFIG_SPARC32
-static int interrupts[PROMINTR_MAX] __initdata = { 0 };
-#endif
+struct sbus_bus *sbus_root;
 
 #ifdef CONFIG_PCI
 extern int pcic_present(void);
 #endif
 
-/* Perhaps when I figure out more about the iommu we'll put a
- * device registration routine here that probe_sbus() calls to
- * setup the iommu for each Sbus.
- */
-
-/* We call this for each SBus device, and fill the structure based
- * upon the prom device tree.  We return the start of memory after
- * the things we have allocated.
- */
-
-/* #define DEBUG_FILL */
-
 static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
 {
        unsigned long address, base;
@@ -52,117 +34,30 @@ static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
        len = prom_getproperty(prom_node, "reg",
                               (char *) sdev->reg_addrs,
                               sizeof(sdev->reg_addrs));
-       if (len == -1) {
-               sdev->num_registers = 0;
-               goto no_regs;
-       }
-
-       if (len % sizeof(struct linux_prom_registers)) {
-               prom_printf("fill_sbus_device: proplen for regs of %s "
-                           " was %d, need multiple of %d\n",
-                           sdev->prom_name, len,
-                           (int) sizeof(struct linux_prom_registers));
-               prom_halt();
-       }
-       if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) {
-               prom_printf("fill_sbus_device: Too many register properties "
-                           "for device %s, len=%d\n",
-                           sdev->prom_name, len);
-               prom_halt();
-       }
-       sdev->num_registers = len / sizeof(struct linux_prom_registers);
-       sdev->ranges_applied = 0;
+       sdev->num_registers = 0;
+       if (len != -1) {
+               sdev->num_registers =
+                       len / sizeof(struct linux_prom_registers);
+               sdev->ranges_applied = 0;
 
-       base = (unsigned long) sdev->reg_addrs[0].phys_addr;
+               base = (unsigned long) sdev->reg_addrs[0].phys_addr;
 
-       /* Compute the slot number. */
-       if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) {
-               sdev->slot = sbus_dev_slot(base);
-       } else {
-               sdev->slot = sdev->reg_addrs[0].which_io;
+               /* Compute the slot number. */
+               if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m)
+                       sdev->slot = sbus_dev_slot(base);
+               else
+                       sdev->slot = sdev->reg_addrs[0].which_io;
        }
 
-no_regs:
        len = prom_getproperty(prom_node, "ranges",
                               (char *)sdev->device_ranges,
                               sizeof(sdev->device_ranges));
-       if (len == -1) {
-               sdev->num_device_ranges = 0;
-               goto no_ranges;
-       }
-       if (len % sizeof(struct linux_prom_ranges)) {
-               prom_printf("fill_sbus_device: proplen for ranges of %s "
-                           " was %d, need multiple of %d\n",
-                           sdev->prom_name, len,
-                           (int) sizeof(struct linux_prom_ranges));
-               prom_halt();
-       }
-       if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) {
-               prom_printf("fill_sbus_device: Too many range properties "
-                           "for device %s, len=%d\n",
-                           sdev->prom_name, len);
-               prom_halt();
-       }
-       sdev->num_device_ranges =
-               len / sizeof(struct linux_prom_ranges);
+       sdev->num_device_ranges = 0;
+       if (len != -1)
+               sdev->num_device_ranges =
+                       len / sizeof(struct linux_prom_ranges);
 
-no_ranges:
-       /* XXX Unfortunately, IRQ issues are very arch specific.
-        * XXX Pull this crud out into an arch specific area
-        * XXX at some point. -DaveM
-        */
-#ifdef CONFIG_SPARC64
-       len = prom_getproperty(prom_node, "interrupts",
-                              (char *) irqs, sizeof(irqs));
-       if (len == -1 || len == 0) {
-               sdev->irqs[0] = 0;
-               sdev->num_irqs = 0;
-       } else {
-               unsigned int pri = irqs[0].pri;
-
-               sdev->num_irqs = 1;
-               if (pri < 0x20)
-                       pri += sdev->slot * 8;
-
-               sdev->irqs[0] = sbus_build_irq(sdev->bus, pri);
-       }
-#endif /* CONFIG_SPARC64 */
-
-#ifdef CONFIG_SPARC32
-       len = prom_getproperty(prom_node, "intr",
-                              (char *)irqs, sizeof(irqs));
-       if (len != -1) {
-               sdev->num_irqs = len / 8;
-               if (sdev->num_irqs == 0) {
-                       sdev->irqs[0] = 0;
-               } else if (sparc_cpu_model == sun4d) {
-                       extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
-
-                       for (len = 0; len < sdev->num_irqs; len++)
-                               sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri);
-               } else {
-                       for (len = 0; len < sdev->num_irqs; len++)
-                               sdev->irqs[len] = irqs[len].pri;
-               }
-       } else {
-               /* No "intr" node found-- check for "interrupts" node.
-                * This node contains SBus interrupt levels, not IPLs
-                * as in "intr", and no vector values.  We convert 
-                * SBus interrupt levels to PILs (platform specific).
-                */
-               len = prom_getproperty(prom_node, "interrupts", 
-                                       (char *)interrupts, sizeof(interrupts));
-               if (len == -1) {
-                       sdev->irqs[0] = 0;
-                       sdev->num_irqs = 0;
-               } else {
-                       sdev->num_irqs = len / sizeof(int);
-                       for (len = 0; len < sdev->num_irqs; len++) {
-                               sdev->irqs[len] = sbint_to_irq(sdev, interrupts[len]);
-                       }
-               }
-       } 
-#endif /* CONFIG_SPARC32 */
+       sbus_fill_device_irq(sdev);
 }
 
 /* This routine gets called from whoever needs the sbus first, to scan
index a13cddc..76654fa 100644 (file)
@@ -102,6 +102,7 @@ sbus_is_slave(struct sbus_dev *dev)
 #define sbus_can_dma_64bit(sdev)       (0) /* actually, sparc_cpu_model==sun4d */
 #define sbus_can_burst64(sdev)         (0) /* actually, sparc_cpu_model==sun4d */
 extern void sbus_set_sbus64(struct sbus_dev *, int);
+extern void sbus_fill_device_irq(struct sbus_dev *);
 
 /* These yield IOMMU mappings in consistent mode. */
 extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp);
index 48279e1..ca2054d 100644 (file)
@@ -95,6 +95,7 @@ extern struct sbus_bus *sbus_root;
 #define sbus_can_dma_64bit(sdev)       (1)
 #define sbus_can_burst64(sdev)         (1)
 extern void sbus_set_sbus64(struct sbus_dev *, int);
+extern void sbus_fill_device_irq(struct sbus_dev *);
 
 /* These yield IOMMU mappings in consistent mode. */
 extern void *sbus_alloc_consistent(struct sbus_dev *, size_t, dma_addr_t *dma_addrp);