diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-10 18:37:51 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-10 18:37:51 +0300 |
commit | 3ae0af12b458461f36dfddb26e54056be32928dd (patch) | |
tree | 063059f24f42506ce2a86374a3b6e2b7a8ae3fcf /arch/ppc | |
parent | 3b44f137b9a846c5452d9e6e1271b79b1dbcc942 (diff) | |
parent | 7c43ee40ec602db3fa27e6e2d4f092f06ab0901c (diff) | |
download | linux-3ae0af12b458461f36dfddb26e54056be32928dd.tar.xz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge
Diffstat (limited to 'arch/ppc')
-rw-r--r-- | arch/ppc/boot/include/of1275.h | 3 | ||||
-rw-r--r-- | arch/ppc/boot/of1275/Makefile | 2 | ||||
-rw-r--r-- | arch/ppc/boot/of1275/call_prom.c | 74 | ||||
-rw-r--r-- | arch/ppc/boot/of1275/claim.c | 97 | ||||
-rw-r--r-- | arch/ppc/boot/of1275/finddevice.c | 19 | ||||
-rw-r--r-- | arch/ppc/boot/openfirmware/Makefile | 3 | ||||
-rw-r--r-- | arch/ppc/kernel/Makefile | 5 | ||||
-rw-r--r-- | arch/ppc/kernel/head_booke.h | 2 | ||||
-rw-r--r-- | arch/ppc/kernel/irq.c | 165 | ||||
-rw-r--r-- | arch/ppc/kernel/misc.S | 4 | ||||
-rw-r--r-- | arch/ppc/kernel/ppc_ksyms.c | 7 | ||||
-rw-r--r-- | arch/ppc/kernel/setup.c | 1 | ||||
-rw-r--r-- | arch/ppc/platforms/pmac_pic.c | 3 | ||||
-rw-r--r-- | arch/ppc/platforms/prep_setup.c | 9 |
14 files changed, 178 insertions, 216 deletions
diff --git a/arch/ppc/boot/include/of1275.h b/arch/ppc/boot/include/of1275.h index 69173df76db0..4ed88acfa73a 100644 --- a/arch/ppc/boot/include/of1275.h +++ b/arch/ppc/boot/include/of1275.h @@ -19,6 +19,9 @@ extern prom_entry of_prom_entry; /* function declarations */ +int call_prom(const char *service, int nargs, int nret, ...); +int call_prom_ret(const char *service, int nargs, int nret, + unsigned int *rets, ...); void * claim(unsigned int virt, unsigned int size, unsigned int align); int map(unsigned int phys, unsigned int virt, unsigned int size); void enter(void); diff --git a/arch/ppc/boot/of1275/Makefile b/arch/ppc/boot/of1275/Makefile index 02e6f235d7cb..0b979c004972 100644 --- a/arch/ppc/boot/of1275/Makefile +++ b/arch/ppc/boot/of1275/Makefile @@ -3,4 +3,4 @@ # lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \ - ofstdio.o read.o release.o write.o map.o + ofstdio.o read.o release.o write.o map.o call_prom.o diff --git a/arch/ppc/boot/of1275/call_prom.c b/arch/ppc/boot/of1275/call_prom.c new file mode 100644 index 000000000000..9479a3a2b8c7 --- /dev/null +++ b/arch/ppc/boot/of1275/call_prom.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 1996-2005 Paul Mackerras. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include "of1275.h" +#include <stdarg.h> + +int call_prom(const char *service, int nargs, int nret, ...) +{ + int i; + struct prom_args { + const char *service; + int nargs; + int nret; + unsigned int args[12]; + } args; + va_list list; + + args.service = service; + args.nargs = nargs; + args.nret = nret; + + va_start(list, nret); + for (i = 0; i < nargs; i++) + args.args[i] = va_arg(list, unsigned int); + va_end(list); + + for (i = 0; i < nret; i++) + args.args[nargs+i] = 0; + + if (of_prom_entry(&args) < 0) + return -1; + + return (nret > 0)? args.args[nargs]: 0; +} + +int call_prom_ret(const char *service, int nargs, int nret, + unsigned int *rets, ...) +{ + int i; + struct prom_args { + const char *service; + int nargs; + int nret; + unsigned int args[12]; + } args; + va_list list; + + args.service = service; + args.nargs = nargs; + args.nret = nret; + + va_start(list, rets); + for (i = 0; i < nargs; i++) + args.args[i] = va_arg(list, unsigned int); + va_end(list); + + for (i = 0; i < nret; i++) + args.args[nargs+i] = 0; + + if (of_prom_entry(&args) < 0) + return -1; + + if (rets != (void *) 0) + for (i = 1; i < nret; ++i) + rets[i-1] = args.args[nargs+i]; + + return (nret > 0)? args.args[nargs]: 0; +} diff --git a/arch/ppc/boot/of1275/claim.c b/arch/ppc/boot/of1275/claim.c index 13169a5c4339..1ed3aeeff8ae 100644 --- a/arch/ppc/boot/of1275/claim.c +++ b/arch/ppc/boot/of1275/claim.c @@ -9,27 +9,84 @@ */ #include "of1275.h" +#include "nonstdio.h" -void * -claim(unsigned int virt, unsigned int size, unsigned int align) +/* + * Older OF's require that when claiming a specific range of addresses, + * we claim the physical space in the /memory node and the virtual + * space in the chosen mmu node, and then do a map operation to + * map virtual to physical. + */ +static int need_map = -1; +static ihandle chosen_mmu; +static phandle memory; + +/* returns true if s2 is a prefix of s1 */ +static int string_match(const char *s1, const char *s2) +{ + for (; *s2; ++s2) + if (*s1++ != *s2) + return 0; + return 1; +} + +static int check_of_version(void) +{ + phandle oprom, chosen; + char version[64]; + + oprom = finddevice("/openprom"); + if (oprom == OF_INVALID_HANDLE) + return 0; + if (getprop(oprom, "model", version, sizeof(version)) <= 0) + return 0; + version[sizeof(version)-1] = 0; + printf("OF version = '%s'\n", version); + if (!string_match(version, "Open Firmware, 1.") + && !string_match(version, "FirmWorks,3.")) + return 0; + chosen = finddevice("/chosen"); + if (chosen == OF_INVALID_HANDLE) { + chosen = finddevice("/chosen@0"); + if (chosen == OF_INVALID_HANDLE) { + printf("no chosen\n"); + return 0; + } + } + if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { + printf("no mmu\n"); + return 0; + } + memory = (ihandle) call_prom("open", 1, 1, "/memory"); + if (memory == OF_INVALID_HANDLE) { + memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); + if (memory == OF_INVALID_HANDLE) { + printf("no memory node\n"); + return 0; + } + } + printf("old OF detected\n"); + return 1; +} + +void *claim(unsigned int virt, unsigned int size, unsigned int align) { - struct prom_args { - char *service; - int nargs; - int nret; - unsigned int virt; - unsigned int size; - unsigned int align; - void *ret; - } args; + int ret; + unsigned int result; - args.service = "claim"; - args.nargs = 3; - args.nret = 1; - args.virt = virt; - args.size = size; - args.align = align; - args.ret = (void *) 0; - (*of_prom_entry)(&args); - return args.ret; + if (need_map < 0) + need_map = check_of_version(); + if (align || !need_map) + return (void *) call_prom("claim", 3, 1, virt, size, align); + + ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, + align, size, virt); + if (ret != 0 || result == -1) + return (void *) -1; + ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, + align, size, virt); + /* 0x12 == coherent + read/write */ + ret = call_prom("call-method", 6, 1, "map", chosen_mmu, + 0x12, size, virt, virt); + return virt; } diff --git a/arch/ppc/boot/of1275/finddevice.c b/arch/ppc/boot/of1275/finddevice.c index 2c0f7cbb793e..0dcb1201b772 100644 --- a/arch/ppc/boot/of1275/finddevice.c +++ b/arch/ppc/boot/of1275/finddevice.c @@ -10,22 +10,7 @@ #include "of1275.h" -phandle -finddevice(const char *name) +phandle finddevice(const char *name) { - struct prom_args { - char *service; - int nargs; - int nret; - const char *devspec; - phandle device; - } args; - - args.service = "finddevice"; - args.nargs = 1; - args.nret = 1; - args.devspec = name; - args.device = OF_INVALID_HANDLE; - (*of_prom_entry)(&args); - return args.device; + return (phandle) call_prom("finddevice", 1, 1, name); } diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile index 03415238fabf..83a6433459ce 100644 --- a/arch/ppc/boot/openfirmware/Makefile +++ b/arch/ppc/boot/openfirmware/Makefile @@ -80,8 +80,7 @@ $(obj)/note: $(utils)/mknote FORCE $(call if_changed,mknote) -$(obj)/coffcrt0.o: EXTRA_AFLAGS := -traditional -DXCOFF -$(obj)/crt0.o: EXTRA_AFLAGS := -traditional +$(obj)/coffcrt0.o: EXTRA_AFLAGS := -DXCOFF targets += coffcrt0.o crt0.o $(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE $(call if_changed_dep,as_o_S) diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 76a55a438f23..17a4da65e275 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -12,7 +12,7 @@ extra-$(CONFIG_6xx) += idle_6xx.o extra-$(CONFIG_POWER4) += idle_power4.o extra-y += vmlinux.lds -obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ +obj-y := entry.o traps.o idle.o time.o misc.o \ process.o align.o \ setup.o \ ppc_htab.o @@ -38,8 +38,7 @@ endif # These are here while we do the architecture merge else -obj-y := irq.o idle.o \ - align.o +obj-y := idle.o align.o obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h index aeb349b47af3..f3d274c6b231 100644 --- a/arch/ppc/kernel/head_booke.h +++ b/arch/ppc/kernel/head_booke.h @@ -358,6 +358,6 @@ label: NORMAL_EXCEPTION_PROLOG; \ bne load_up_fpu; /* if from user, just load it up */ \ addi r3,r1,STACK_FRAME_OVERHEAD; \ - EXC_XFER_EE_LITE(0x800, KernelFP) + EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception) #endif /* __HEAD_BOOKE_H__ */ diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c deleted file mode 100644 index fbb2b9f8922c..000000000000 --- a/arch/ppc/kernel/irq.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * arch/ppc/kernel/irq.c - * - * Derived from arch/i386/kernel/irq.c - * Copyright (C) 1992 Linus Torvalds - * Adapted from arch/i386 by Gary Thomas - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * Updated and modified by Cort Dougan <cort@fsmlabs.com> - * Copyright (C) 1996-2001 Cort Dougan - * Adapted for Power Macintosh by Paul Mackerras - * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) - * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). - * - * This file contains the code used by various IRQ handling routines: - * asking for different IRQ's should be done through these routines - * instead of just grabbing them. Thus setups with different IRQ numbers - * shouldn't result in any weird surprises, and installing new handlers - * should be easier. - * - * The MPC8xx has an interrupt mask in the SIU. If a bit is set, the - * interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit - * mask register (of which only 16 are defined), hence the weird shifting - * and complement of the cached_irq_mask. I want to be able to stuff - * this right into the SIU SMASK register. - * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx - * to reduce code space and undefined function references. - */ - -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/threads.h> -#include <linux/kernel_stat.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/timex.h> -#include <linux/config.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/irq.h> -#include <linux/proc_fs.h> -#include <linux/random.h> -#include <linux/seq_file.h> -#include <linux/cpumask.h> -#include <linux/profile.h> -#include <linux/bitops.h> - -#include <asm/uaccess.h> -#include <asm/system.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/irq.h> -#include <asm/cache.h> -#include <asm/prom.h> -#include <asm/ptrace.h> -#include <asm/machdep.h> - -#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) - -extern atomic_t ipi_recv; -extern atomic_t ipi_sent; - -#define MAXCOUNT 10000000 - -int ppc_spurious_interrupts = 0; -struct irqaction *ppc_irq_action[NR_IRQS]; -unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; -unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; -atomic_t ppc_n_lost_interrupts; - -#ifdef CONFIG_TAU_INT -extern int tau_initialized; -extern int tau_interrupts(int); -#endif - -int show_interrupts(struct seq_file *p, void *v) -{ - int i = *(loff_t *) v, j; - struct irqaction * action; - unsigned long flags; - - if (i == 0) { - seq_puts(p, " "); - for (j=0; j<NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "CPU%d ", j); - seq_putc(p, '\n'); - } - - if (i < NR_IRQS) { - spin_lock_irqsave(&irq_desc[i].lock, flags); - action = irq_desc[i].action; - if ( !action || !action->handler ) - goto skip; - seq_printf(p, "%3d: ", i); -#ifdef CONFIG_SMP - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", - kstat_cpu(j).irqs[i]); -#else - seq_printf(p, "%10u ", kstat_irqs(i)); -#endif /* CONFIG_SMP */ - if (irq_desc[i].handler) - seq_printf(p, " %s ", irq_desc[i].handler->typename); - else - seq_puts(p, " None "); - seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge "); - seq_printf(p, " %s", action->name); - for (action = action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); - seq_putc(p, '\n'); -skip: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } else if (i == NR_IRQS) { -#ifdef CONFIG_TAU_INT - if (tau_initialized){ - seq_puts(p, "TAU: "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", tau_interrupts(j)); - seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); - } -#endif -#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) - /* should this be per processor send/receive? */ - seq_printf(p, "IPI (recv/sent): %10u/%u\n", - atomic_read(&ipi_recv), atomic_read(&ipi_sent)); -#endif - seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); - } - return 0; -} - -void do_IRQ(struct pt_regs *regs) -{ - int irq, first = 1; - irq_enter(); - - /* - * Every platform is required to implement ppc_md.get_irq. - * This function will either return an irq number or -1 to - * indicate there are no more pending. But the first time - * through the loop this means there wasn't and IRQ pending. - * The value -2 is for buggy hardware and means that this IRQ - * has already been handled. -- Tom - */ - while ((irq = ppc_md.get_irq(regs)) >= 0) { - __do_IRQ(irq, regs); - first = 0; - } - if (irq != -2 && first) - /* That's not SMP safe ... but who cares ? */ - ppc_spurious_interrupts++; - irq_exit(); -} - -void __init init_IRQ(void) -{ - ppc_md.init_IRQ(); -} diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index ae6af29938a1..5e61124581d0 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -497,9 +497,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) * and invalidate the corresponding instruction cache blocks. * This is a no-op on the 601. * - * flush_icache_range(unsigned long start, unsigned long stop) + * __flush_icache_range(unsigned long start, unsigned long stop) */ -_GLOBAL(flush_icache_range) +_GLOBAL(__flush_icache_range) BEGIN_FTR_SECTION blr /* for 601, do nothing */ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index e0ca61b37f4f..66073f775193 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -46,6 +46,7 @@ #include <asm/btext.h> #include <asm/div64.h> #include <asm/xmon.h> +#include <asm/signal.h> #ifdef CONFIG_8xx #include <asm/commproc.h> @@ -57,7 +58,6 @@ extern void machine_check_exception(struct pt_regs *regs); extern void alignment_exception(struct pt_regs *regs); extern void program_check_exception(struct pt_regs *regs); extern void single_step_exception(struct pt_regs *regs); -extern int do_signal(sigset_t *, struct pt_regs *); extern int pmac_newworld; extern int sys_sigreturn(struct pt_regs *regs); @@ -78,7 +78,6 @@ EXPORT_SYMBOL(program_check_exception); EXPORT_SYMBOL(single_step_exception); EXPORT_SYMBOL(sys_sigreturn); EXPORT_SYMBOL(ppc_n_lost_interrupts); -EXPORT_SYMBOL(ppc_lost_interrupts); EXPORT_SYMBOL(ISA_DMA_THRESHOLD); EXPORT_SYMBOL(DMA_MODE_READ); @@ -176,6 +175,7 @@ EXPORT_SYMBOL(pci_bus_to_phys); #endif /* CONFIG_PCI */ #ifdef CONFIG_NOT_COHERENT_CACHE +extern void flush_dcache_all(void); EXPORT_SYMBOL(flush_dcache_all); #endif @@ -217,9 +217,6 @@ EXPORT_SYMBOL(adb_try_handler_change); EXPORT_SYMBOL(cuda_request); EXPORT_SYMBOL(cuda_poll); #endif /* CONFIG_ADB_CUDA */ -#ifdef CONFIG_PPC_MULTIPLATFORM -EXPORT_SYMBOL(_machine); -#endif #ifdef CONFIG_PPC_PMAC EXPORT_SYMBOL(sys_ctrler); EXPORT_SYMBOL(pmac_newworld); diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 6bcb85d2b7fd..dc55e1abc45b 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -76,6 +76,7 @@ unsigned int DMA_MODE_WRITE; #ifdef CONFIG_PPC_MULTIPLATFORM int _machine = 0; +EXPORT_SYMBOL(_machine); extern void prep_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c index 9f2d95ea8564..4742bf609357 100644 --- a/arch/ppc/platforms/pmac_pic.c +++ b/arch/ppc/platforms/pmac_pic.c @@ -75,6 +75,9 @@ static DEFINE_SPINLOCK(pmac_pic_lock); #define GATWICK_IRQ_POOL_SIZE 10 static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; +#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) +static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; + /* * Mark an irq as "lost". This is only used on the pmac * since it can lose interrupts (see pmac_set_irq_mask). diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index 067d7d53b81e..4415748071dc 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c @@ -61,6 +61,15 @@ #include <asm/pci-bridge.h> #include <asm/todc.h> +/* prep registers for L2 */ +#define CACHECRBA 0x80000823 /* Cache configuration register address */ +#define L2CACHE_MASK 0x03 /* Mask for 2 L2 Cache bits */ +#define L2CACHE_512KB 0x00 /* 512KB */ +#define L2CACHE_256KB 0x01 /* 256KB */ +#define L2CACHE_1MB 0x02 /* 1MB */ +#define L2CACHE_NONE 0x03 /* NONE */ +#define L2CACHE_PARITY 0x08 /* Mask for L2 Cache Parity Protected bit */ + TODC_ALLOC(); unsigned char ucSystemType; |