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 | kernel_samsung_espresso10-8fae097debdf8ac9b66d220ac258535ea09f3898.zip kernel_samsung_espresso10-8fae097debdf8ac9b66d220ac258535ea09f3898.tar.gz kernel_samsung_espresso10-8fae097debdf8ac9b66d220ac258535ea09f3898.tar.bz2  | |
[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 f9ff297..00cf411 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 8812417..8f7877a 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 5d30a3e..6e9b260 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 a13cddc..76654fa 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 48279e1..ca2054d 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);  | 
