diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-18 00:24:27 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-18 00:24:27 +0000 |
commit | b9558d5f86c471a125abf1fb3a3882fb053b1f8c (patch) | |
tree | 707b53ec64e740a7da87d5f36485e3cd9b1c794e /arch/sparc/kernel/ebus.c | |
parent | b3ac367c7a3e6047abe74817db27e34e759f279f (diff) |
Merge with Linux 2.3.41.
Diffstat (limited to 'arch/sparc/kernel/ebus.c')
-rw-r--r-- | arch/sparc/kernel/ebus.c | 100 |
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) |