diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-06-20 15:23:28 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-23 23:15:00 -0700 |
commit | 8fae097debdf8ac9b66d220ac258535ea09f3898 (patch) | |
tree | 9c022cbf14e9174946a503b116fdf7376b8ce0ce | |
parent | d384ea691fe4ea8c2dd5b9b8d9042eb181776f18 (diff) | |
download | lwn-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.c | 46 | ||||
-rw-r--r-- | arch/sparc64/kernel/sbus.c | 21 | ||||
-rw-r--r-- | drivers/sbus/sbus.c | 143 | ||||
-rw-r--r-- | include/asm-sparc/sbus.h | 1 | ||||
-rw-r--r-- | include/asm-sparc64/sbus.h | 1 |
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); |