summaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/ebus.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-18 00:24:27 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-18 00:24:27 +0000
commitb9558d5f86c471a125abf1fb3a3882fb053b1f8c (patch)
tree707b53ec64e740a7da87d5f36485e3cd9b1c794e /arch/sparc/kernel/ebus.c
parentb3ac367c7a3e6047abe74817db27e34e759f279f (diff)
Merge with Linux 2.3.41.
Diffstat (limited to 'arch/sparc/kernel/ebus.c')
-rw-r--r--arch/sparc/kernel/ebus.c100
1 files changed, 69 insertions, 31 deletions
diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c
index c1ef01be3..c9972ab16 100644
--- a/arch/sparc/kernel/ebus.c
+++ b/arch/sparc/kernel/ebus.c
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.8 1999/11/27 22:40:38 zaitcev Exp $
+/* $Id: ebus.c,v 1.9 2000/01/22 07:35:25 zaitcev Exp $
* ebus.c: PCI to EBus bridge device.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -22,14 +22,6 @@
#include <asm/oplib.h>
#include <asm/bpp.h>
-#undef PROM_DEBUG
-
-#if 0 /* separate from PROM_DEBUG for the sake of PROLL */
-#define dprintk prom_printf
-#else
-#define dprintk printk
-#endif
-
struct linux_ebus *ebus_chain = 0;
#ifdef CONFIG_SUN_OPENPROMIO
@@ -51,11 +43,62 @@ extern int envctrl_init(void);
/* We are together with pcic.c under CONFIG_PCI. */
extern unsigned int pcic_pin_to_irq(unsigned int, char *name);
+/*
+ * IRQ Blacklist
+ * Here we list PROMs and systems that are known to supply crap as IRQ numbers.
+ */
+struct ebus_device_irq {
+ char *name;
+ unsigned int pin;
+};
+
+struct ebus_system_entry {
+ char *esname;
+ struct ebus_device_irq *ipt;
+};
+
+static struct ebus_device_irq je1_1[] = {
+ { "8042", 3 },
+ { "SUNW,CS4231", 0 },
+ { "parallel", 0 },
+ { "se", 2 },
+ { 0, 0 }
+};
+
+/*
+ * Gleb's JE1 supplied reasonable pin numbers, but mine did not (OBP 2.32).
+ * Blacklist the sucker... Note that Gleb's system will work.
+ */
+static struct ebus_system_entry ebus_blacklist[] = {
+ { "SUNW,JavaEngine1", je1_1 },
+ { 0, 0 }
+};
+
+static struct ebus_device_irq *ebus_blackp = NULL;
+
+/*
+ */
static inline unsigned long ebus_alloc(size_t size)
{
return (unsigned long)kmalloc(size, GFP_ATOMIC);
}
+/*
+ */
+int __init ebus_blacklist_irq(char *name)
+{
+ struct ebus_device_irq *dp;
+
+ if ((dp = ebus_blackp) != NULL) {
+ for (; dp->name != NULL; dp++) {
+ if (strcmp(name, dp->name) == 0) {
+ return pcic_pin_to_irq(dp->pin, name);
+ }
+ }
+ }
+ return 0;
+}
+
void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
struct linux_ebus_child *dev)
{
@@ -81,14 +124,10 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
dev->resource[i].start = dev->parent->resource[regs[i]].start; /* XXX resource */
}
- /*
- * Houston, we have a problem...
- * Sometimes PROM supplies absolutely meaningless properties.
- * Still, we take what it gives since we have nothing better.
- * Children of ebus may be wired on any input pin of PCIC.
- */
- len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
- if ((len == -1) || (len == 0)) {
+ if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) {
+ dev->num_irqs = 1;
+ } else if ((len = prom_getproperty(node, "interrupts",
+ (char *)&irqs, sizeof(irqs)) == -1) || (len == 0)) {
dev->num_irqs = 0;
dev->irqs[0] = 0;
if (dev->parent->num_irqs != 0) {
@@ -177,8 +216,10 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
dev->resource[i].start = baseaddr; /* XXX Unaligned */
}
- len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
- if ((len == -1) || (len == 0)) {
+ if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) {
+ dev->num_irqs = 1;
+ } else if ((len = prom_getproperty(node, "interrupts",
+ (char *)&irqs, sizeof(irqs)) == -1) || (len == 0)) {
dev->num_irqs = 0;
if ((dev->irqs[0] = dev->bus->self->irq) != 0) {
dev->num_irqs = 1;
@@ -226,6 +267,7 @@ void __init ebus_init(void)
struct linux_pbm_info *pbm;
struct linux_ebus_device *dev;
struct linux_ebus *ebus;
+ struct ebus_system_entry *sp;
struct pci_dev *pdev;
struct pcidev_cookie *cookie;
char lbuf[128];
@@ -238,11 +280,16 @@ void __init ebus_init(void)
if (!pci_present())
return;
+ prom_getstring(prom_root_node, "name", lbuf, sizeof(lbuf));
+ for (sp = ebus_blacklist; sp->esname != NULL; sp++) {
+ if (strcmp(lbuf, sp->esname) == 0) {
+ ebus_blackp = sp->ipt;
+ break;
+ }
+ }
+
pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0);
if (!pdev) {
-#ifdef PROM_DEBUG
- dprintk("ebus: No EBus's found.\n");
-#endif
return;
}
cookie = pdev->sysdata;
@@ -253,9 +300,6 @@ void __init ebus_init(void)
ebus->next = 0;
while (ebusnd) {
-#ifdef PROM_DEBUG
- dprintk("ebus%d:", num_ebus);
-#endif
prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf));
ebus->prom_node = ebusnd;
@@ -284,13 +328,7 @@ void __init ebus_init(void)
addr = regs[reg].phys_lo;
*base++ = addr;
-#ifdef PROM_DEBUG
- dprintk(" %lx[%x]", addr, regs[reg].size_lo);
-#endif
}
-#ifdef PROM_DEBUG
- dprintk("\n");
-#endif
nd = prom_getchild(ebusnd);
if (!nd)