Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8fae097d authored by David S. Miller's avatar David S. Miller
Browse files

[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: default avatarDavid S. Miller <davem@davemloft.net>
parent d384ea69
Loading
Loading
Loading
Loading
+45 −1
Original line number Diff line number Diff line
@@ -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.
+21 −0
Original line number Diff line number Diff line
@@ -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);
	}
}
+19 −124
Original line number Diff line number Diff line
/* $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);
	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;

		/* Compute the slot number. */
	if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) {
		if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m)
			sdev->slot = sbus_dev_slot(base);
	} else {
		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();
	}
	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
+1 −0
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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);