summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-06-20 15:23:28 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-23 23:15:00 -0700
commit8fae097debdf8ac9b66d220ac258535ea09f3898 (patch)
tree9c022cbf14e9174946a503b116fdf7376b8ce0ce
parentd384ea691fe4ea8c2dd5b9b8d9042eb181776f18 (diff)
downloadlwn-8fae097debdf8ac9b66d220ac258535ea09f3898.tar.gz
lwn-8fae097debdf8ac9b66d220ac258535ea09f3898.zip
[SBUS]: Start cleaning up generic sbus support layer.
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>
-rw-r--r--arch/sparc/kernel/ioport.c46
-rw-r--r--arch/sparc64/kernel/sbus.c21
-rw-r--r--drivers/sbus/sbus.c143
-rw-r--r--include/asm-sparc/sbus.h1
-rw-r--r--include/asm-sparc64/sbus.h1
5 files changed, 87 insertions, 125 deletions
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index f9ff29734848..00cf41182912 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -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.
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 8812417247d4..8f7877ac858f 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -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);
+ }
+}
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index 5d30a3ebfccd..6e9b2608202b 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -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>
@@ -17,29 +16,12 @@
#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
diff --git a/include/asm-sparc/sbus.h b/include/asm-sparc/sbus.h
index a13cddcecec5..76654fa23091 100644
--- a/include/asm-sparc/sbus.h
+++ b/include/asm-sparc/sbus.h
@@ -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);
diff --git a/include/asm-sparc64/sbus.h b/include/asm-sparc64/sbus.h
index 48279e10f385..ca2054da2430 100644
--- a/include/asm-sparc64/sbus.h
+++ b/include/asm-sparc64/sbus.h
@@ -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);