diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
commit | db7d4daea91e105e3859cf461d7e53b9b77454b2 (patch) | |
tree | 9bb65b95440af09e8aca63abe56970dd3360cc57 /arch/sparc64/kernel/starfire.c | |
parent | 9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff) |
Merge with Linux 2.2.8.
Diffstat (limited to 'arch/sparc64/kernel/starfire.c')
-rw-r--r-- | arch/sparc64/kernel/starfire.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/starfire.c b/arch/sparc64/kernel/starfire.c new file mode 100644 index 000000000..38f33ecd6 --- /dev/null +++ b/arch/sparc64/kernel/starfire.c @@ -0,0 +1,121 @@ +/* $Id: starfire.c,v 1.2 1998/12/09 18:53:11 davem Exp $ + * starfire.c: Starfire/E10000 support. + * + * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com) + */ + +#include <linux/kernel.h> +#include <linux/malloc.h> + +#include <asm/page.h> +#include <asm/oplib.h> +#include <asm/smp.h> + +/* A few places around the kernel check this to see if + * they need to call us to do things in a Starfire specific + * way. + */ +int this_is_starfire = 0; + +void starfire_check(void) +{ + int ssnode = prom_finddevice("/ssp-serial"); + + if(ssnode != 0 && ssnode != -1) { + int i; + + this_is_starfire = 1; + + /* Now must fixup cpu MIDs. OBP gave us a logical + * linear cpuid number, not the real upaid. + */ + for(i = 0; i < linux_num_cpus; i++) { + unsigned int mid = linux_cpus[i].mid; + + mid = (((mid & 0x3c) << 1) | + ((mid & 0x40) >> 4) | + (mid & 0x3)); + + linux_cpus[i].mid = mid; + } + } +} + +int starfire_hard_smp_processor_id(void) +{ + return *((unsigned int *) __va(0x1fff40000d0)); +} + +/* Each Starfire board has 32 registers which perform translation + * and delivery of traditional interrupt packets into the extended + * Starfire hardware format. Essentially UPAID's now have 2 more + * bits than in all previous Sun5 systems. + */ +struct starfire_irqinfo { + unsigned int *imap_slots[32]; + unsigned int *tregs[32]; + struct starfire_irqinfo *next; + int upaid, hwmid; +}; + +static struct starfire_irqinfo *sflist = NULL; + +/* Beam me up Scott(McNeil)y... */ +void *starfire_hookup(int upaid) +{ + struct starfire_irqinfo *p; + unsigned long treg_base, hwmid, i; + + p = kmalloc(sizeof(*p), GFP_KERNEL); + if(!p) { + prom_printf("starfire_hookup: No memory, this is insane.\n"); + prom_halt(); + } + treg_base = 0x100fc000000UL; + hwmid = ((upaid & 0x3c) << 1) | + ((upaid & 0x40) >> 4) | + (upaid & 0x3); + p->hwmid = hwmid; + treg_base += (hwmid << 33UL); + treg_base += 0x200UL; + for(i = 0; i < 32; i++) { + p->imap_slots[i] = NULL; + p->tregs[i] = __va(treg_base + (i * 0x10)); + } + p->upaid = upaid; + p->next = sflist; + sflist = p; + + return (void *) p; +} + +unsigned int starfire_translate(unsigned int *imap, + unsigned int upaid) +{ + struct starfire_irqinfo *p; + unsigned int bus_hwmid; + unsigned int i; + + bus_hwmid = (((unsigned long)imap) >> 33) & 0x7f; + for(p = sflist; p != NULL; p = p->next) + if(p->hwmid == bus_hwmid) + break; + if(p == NULL) { + prom_printf("XFIRE: Cannot find irqinfo for imap %016lx\n", + ((unsigned long)imap)); + prom_halt(); + } + for(i = 0; i < 32; i++) { + if(p->imap_slots[i] == imap || + p->imap_slots[i] == NULL) + break; + } + if(i == 32) { + printk("starfire_translate: Are you kidding me?\n"); + panic("Lucy in the sky...."); + } + p->imap_slots[i] = imap; + *(p->tregs[i]) = upaid; + + return i; +} |