From c0b3ae14f14f53fb0d0453feeeb830a080726155 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 6 Feb 2007 12:03:31 +1100 Subject: [POWERPC] Move of_irq_to_resource from prom.h to prom_parse.c In the powerpc architecture, of_irq_to_resource, currently sitting in prom.h, needs irq_of_parse_and_map and NO_IRQ from asm-powerpc/irq.h. The solution suggested by Benjamin Herrenschmidt is to move it to arch/powerpc/kernel/prom_parse.c. Signed-off-by: Mathieu Desnoyers Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_parse.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index aa40a530729..78ee8d5b07c 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -1042,3 +1042,17 @@ const void *of_get_mac_address(struct device_node *np) } EXPORT_SYMBOL(of_get_mac_address); +int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) +{ + int irq = irq_of_parse_and_map(dev, index); + + /* Only dereference the resource if both the + * resource and the irq are valid. */ + if (r && irq != NO_IRQ) { + r->start = r->end = irq; + r->flags = IORESOURCE_IRQ; + } + + return irq; +} +EXPORT_SYMBOL_GPL(of_irq_to_resource); -- cgit v1.2.3 From c3e8011ad1bf4791a9c6d70ac1b377df93a9f5af Mon Sep 17 00:00:00 2001 From: Christian Krafft Date: Wed, 25 Apr 2007 01:32:02 +1000 Subject: [POWERPC] Uninline of_iomap function There is no big reason to have that function inlined. Signed-off-by: Christian Krafft Acked-by: Arnd Bergmann Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_parse.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 78ee8d5b07c..b5c96af955c 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -1056,3 +1056,14 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) return irq; } EXPORT_SYMBOL_GPL(of_irq_to_resource); + +void __iomem *of_iomap(struct device_node *np, int index) +{ + struct resource res; + + if (of_address_to_resource(np, index, &res)) + return NULL; + + return ioremap(res.start, 1 + res.end - res.start); +} +EXPORT_SYMBOL(of_iomap); -- cgit v1.2.3 From 57d7909e0d2dd54567ae775e22b14076b777042a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 30 Apr 2007 14:06:25 +1000 Subject: [POWERPC] Revise PPC44x MMU code for arch/powerpc This patch takes the definitions for the PPC44x MMU (a software loaded TLB) from asm-ppc/mmu.h, cleans them up of things no longer necessary in arch/powerpc and puts them in a new asm-powerpc/mmu_44x.h file. It also substantially simplifies arch/powerpc/mm/44x_mmu.c and makes a couple of small fixes necessary for the 44x MMU code to build and work properly in arch/powerpc. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/head_44x.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index a15d4b8cce4..9ee6773cf02 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -120,8 +120,8 @@ skpinv: addi r4,r4,1 /* Increment */ * Configure and load pinned entry into TLB slot 63. */ - lis r3,KERNELBASE@h /* Load the kernel virtual address */ - ori r3,r3,KERNELBASE@l + lis r3,PAGE_OFFSET@h + ori r3,r3,PAGE_OFFSET@l /* Kernel is at the base of RAM */ li r4, 0 /* Load the kernel physical address */ -- cgit v1.2.3 From 69d48b409cac747cc0707b05b769e38488a6ad35 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 30 Apr 2007 15:37:06 +1000 Subject: [POWERPC] Fix STRICT_MM_TYPECHECKS Since we don't have it active by default, the STRICT_MM_TYPECHECKS option has bitrotted again. This patch fixes a couple of simple build fixes if the option is selected. First, pud_t mustn't be defined in page.h on 32-bit systems, because it conflicts with the version in the generic pud-folding code. Second, pci_32.c is missing a __pgprot() wrapper call. Third, a couple of PS3 files use constants of type pgprot_t when they need the raw values, we add pgprot_val() calls to fix this. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index f022862de34..e66064b5093 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -1658,7 +1658,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file, int i; if (page_is_ram(pfn)) - return prot; + return __pgprot(prot); prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; -- cgit v1.2.3 From be9c94dd7776467813419f49fabe8017bc2d4c81 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Apr 2007 21:37:15 +1000 Subject: [POWERPC] Fix suspend states again In commit 0fba3a1f39f8b0a50b56c8b068fa52131cbc84c2 (a very long time ago, May 2006), I fixed a bug that caused powermacs to crash when you tried entering standby/mem suspend states. As I'm now getting more familiar with the suspend code I notice a few more things: 1. we previously misunderstood what pm_ops is for, it isn't supposed to be for doing platform dependent suspend/resume stuff that needs to be done for suspend to disk (as we currently try to use it!), it is instead for entering platform dependent suspend states ("standby", "mem"). 2. due to the first point, we never properly save FPU and altivec states when suspending to disk. It probably hasn't hurt yet because the process that writes the "disk" to /sys/power/state uses neither and its context is used. This patch addresses these points as follows: 1. remove all pm_ops from powermac, powermac suspend to ram isn't currently usable via /sys/power/state but is done via the PMU instead. 2. move the code responsible for storing FPU/altivec state into save_processor_state and the set_context() call to restore_processor_state. 3. add a call to kernel_enable_spe() It may look like there is some code removal missing but that is actually because the new suspend.h file overrides the ppc/suspend.h one which was previously used. Signed-off-by: Johannes Berg Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/Makefile | 1 + arch/powerpc/kernel/swsusp.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 arch/powerpc/kernel/swsusp.c (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index e0fa80eca36..949f36a62aa 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o obj-$(CONFIG_TAU) += tau_6xx.o +obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o obj32-$(CONFIG_MODULES) += module_32.o diff --git a/arch/powerpc/kernel/swsusp.c b/arch/powerpc/kernel/swsusp.c new file mode 100644 index 00000000000..b89e4f5a0b0 --- /dev/null +++ b/arch/powerpc/kernel/swsusp.c @@ -0,0 +1,34 @@ +/* + * Common powerpc suspend code for 32 and 64 bits + * + * Copyright 2007 Johannes Berg + * + * 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 +#include +#include +#include +#include + +void save_processor_state(void) +{ + /* + * flush out all the special registers so we don't need + * to save them in the snapshot + */ + flush_fp_to_thread(current); + flush_altivec_to_thread(current); + flush_spe_to_thread(current); +} + +void restore_processor_state(void) +{ +#ifdef CONFIG_PPC32 + set_context(current->active_mm->context.id, current->active_mm->pgd); +#endif +} -- cgit v1.2.3 From 0874dd40bf3c1f291da14b2c554c5640c0b6bf1b Mon Sep 17 00:00:00 2001 From: Takao Shinohara Date: Tue, 1 May 2007 07:01:07 +1000 Subject: [POWERPC] PS3: Fix system slowdown The PS3 HV will deliver soft-disabled interrupts at the next HV call or interrupt. Add an HV call to local_irq_restore() to force the timely delivery of any pending interrupts. This fixes the system slowdown bug reported here http://bugzilla.kernel.org/show_bug.cgi?id=8260 Signed-off-by: Geoff Levand Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/irq.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 6c83fe229e6..5719a530f2d 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -67,6 +67,7 @@ #ifdef CONFIG_PPC64 #include #include +#include #endif int __irq_offset_value; @@ -162,6 +163,16 @@ void local_irq_restore(unsigned long en) local_paca->hard_enabled = en; if ((int)mfspr(SPRN_DEC) < 0) mtspr(SPRN_DEC, 1); + + /* + * Force the delivery of pending soft-disabled interrupts on PS3. + * Any HV call will have this side effect. + */ + if (firmware_has_feature(FW_FEATURE_PS3_LV1)) { + u64 tmp; + lv1_get_version_info(&tmp); + } + hard_irq_enable(); } #endif /* CONFIG_PPC64 */ -- cgit v1.2.3 From 14d1d2f25bca1c4ed45704c8019f6c971c40bba4 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Wed, 2 May 2007 02:05:38 +1000 Subject: [POWERPC] Remove duplicate export of __div64_32. Change 3927f2e8f9afa3424bb51ca81f7abac01ffd0005 moved lib/lib64.c from lib-y to obj-y, preventing the export in ppc_ksyms.c from overriding the one in lib, and thus causing a duplicate-export warning. Signed-off-by: Scott Wood Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/ppc_ksyms.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index ff252aaead1..c96fa9bd35a 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -66,7 +66,6 @@ EXPORT_SYMBOL(clear_pages); EXPORT_SYMBOL(ISA_DMA_THRESHOLD); EXPORT_SYMBOL(DMA_MODE_READ); EXPORT_SYMBOL(DMA_MODE_WRITE); -EXPORT_SYMBOL(__div64_32); EXPORT_SYMBOL(do_signal); EXPORT_SYMBOL(transfer_to_handler); -- cgit v1.2.3 From 9f90b997de4efd5404a8c52f89c400f0f4e2d216 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 30 Apr 2007 11:56:46 +0100 Subject: [POWERPC] Minor fault path optimization Call the kprobes pagefault handler directly instead of going through the complex notifier chain. Signed-off-by: Christoph Hellwig Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/kprobes.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index ef647e7a9dc..c27f41870c8 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -410,7 +410,7 @@ out: return 1; } -static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) +int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); @@ -495,14 +495,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, if (post_kprobe_handler(args->regs)) ret = NOTIFY_STOP; break; - case DIE_PAGE_FAULT: - /* kprobe_running() needs smp_processor_id() */ - preempt_disable(); - if (kprobe_running() && - kprobe_fault_handler(args->regs, args->trapnr)) - ret = NOTIFY_STOP; - preempt_enable(); - break; default: break; } -- cgit v1.2.3 From e9e77ce8718def7838626aa52bed02fe1b9837b9 Mon Sep 17 00:00:00 2001 From: Kevin Corry Date: Thu, 3 May 2007 03:11:49 +1000 Subject: [POWERPC] Change topology_init() to a subsys_initcall Change the powerpc version of topology_init() from an __initcall to a subsys_initcall to match all other architectures. Signed-off-by: Kevin Corry Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 933e214c33e..cae39d9dfe4 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -499,4 +499,4 @@ static int __init topology_init(void) return 0; } -__initcall(topology_init); +subsys_initcall(topology_init); -- cgit v1.2.3 From 44755d11a3c054adf7eb974a4720936563cf7dcf Mon Sep 17 00:00:00 2001 From: will schmidt Date: Thu, 3 May 2007 03:12:34 +1000 Subject: [POWERPC] Add smp_call_function_map and smp_call_function_single Add a new function named smp_call_function_single(). This matches a generic prototype from include/linux/smp.h. Add a function smp_call_function_map(). This is, for the most part, a rename of smp_call_function, with some added cpumask support. smp_call_function and smp_call_function_single call into smp_call_function_map. Lightly tested on 970mp (blade), power4 and power5. Signed-off-by: Will Schmidt cc: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/smp.c | 73 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 21 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index d8e503b2e1a..22f1ef1b310 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -176,10 +176,10 @@ static struct call_data_struct { #define SMP_CALL_TIMEOUT 8 /* - * This function sends a 'generic call function' IPI to all other CPUs - * in the system. + * These functions send a 'generic call function' IPI to other online + * CPUS in the system. * - * [SUMMARY] Run a function on all other CPUs. + * [SUMMARY] Run a function on other CPUs. * The function to run. This must be fast and non-blocking. * An arbitrary pointer to pass to the function. * currently unused. @@ -190,18 +190,26 @@ static struct call_data_struct { * You must not call this function with disabled interrupts or from a * hardware interrupt handler or from a bottom half handler. */ -int smp_call_function (void (*func) (void *info), void *info, int nonatomic, - int wait) -{ +int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, + int wait, cpumask_t map) +{ struct call_data_struct data; - int ret = -1, cpus; + int ret = -1, num_cpus; + int cpu; u64 timeout; /* Can deadlock when called with interrupts disabled */ WARN_ON(irqs_disabled()); + /* remove 'self' from the map */ + if (cpu_isset(smp_processor_id(), map)) + cpu_clear(smp_processor_id(), map); + + /* sanity check the map, remove any non-online processors. */ + cpus_and(map, map, cpu_online_map); + if (unlikely(smp_ops == NULL)) - return -1; + return ret; data.func = func; data.info = info; @@ -213,40 +221,42 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, spin_lock(&call_lock); /* Must grab online cpu count with preempt disabled, otherwise * it can change. */ - cpus = num_online_cpus() - 1; - if (!cpus) { + num_cpus = num_online_cpus() - 1; + if (!num_cpus || cpus_empty(map)) { ret = 0; goto out; } call_data = &data; smp_wmb(); - /* Send a message to all other CPUs and wait for them to respond */ - smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION); + /* Send a message to all CPUs in the map */ + for_each_cpu_mask(cpu, map) + smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNCTION); timeout = get_tb() + (u64) SMP_CALL_TIMEOUT * tb_ticks_per_sec; - /* Wait for response */ - while (atomic_read(&data.started) != cpus) { + /* Wait for indication that they have received the message */ + while (atomic_read(&data.started) != num_cpus) { HMT_low(); if (get_tb() >= timeout) { printk("smp_call_function on cpu %d: other cpus not " - "responding (%d)\n", smp_processor_id(), - atomic_read(&data.started)); + "responding (%d)\n", smp_processor_id(), + atomic_read(&data.started)); debugger(NULL); goto out; } } + /* optionally wait for the CPUs to complete */ if (wait) { - while (atomic_read(&data.finished) != cpus) { + while (atomic_read(&data.finished) != num_cpus) { HMT_low(); if (get_tb() >= timeout) { printk("smp_call_function on cpu %d: other " - "cpus not finishing (%d/%d)\n", - smp_processor_id(), - atomic_read(&data.finished), - atomic_read(&data.started)); + "cpus not finishing (%d/%d)\n", + smp_processor_id(), + atomic_read(&data.finished), + atomic_read(&data.started)); debugger(NULL); goto out; } @@ -262,8 +272,29 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, return ret; } +int smp_call_function(void (*func) (void *info), void *info, int nonatomic, + int wait) +{ + return smp_call_function_map(func,info,nonatomic,wait,cpu_online_map); +} EXPORT_SYMBOL(smp_call_function); +int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int nonatomic, + int wait) +{ + cpumask_t map=CPU_MASK_NONE; + + if (!cpu_online(cpu)) + return -EINVAL; + + if (cpu == smp_processor_id()) + return -EBUSY; + + cpu_set(cpu, map); + return smp_call_function_map(func,info,nonatomic,wait,map); +} +EXPORT_SYMBOL(smp_call_function_single); + void smp_call_function_interrupt(void) { void (*func) (void *info); -- cgit v1.2.3 From d9333afd6a714760c13f76ba275a32ec7bd979c1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 3 May 2007 06:33:51 +1000 Subject: [POWERPC] powermac: Support G5 CPU hotplug This allows "hotplugging" of CPUs on G5 machines. CPUs that are disabled are put into an idle loop with the decrementer frequency set to minimum. To wake them up again we kick them just like when bringing them up. To stop those CPUs from messing with any global state we stop them from entering the timer interrupt. Signed-off-by: Johannes Berg Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/idle_power4.S | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S index ba319547860..5328709eeed 100644 --- a/arch/powerpc/kernel/idle_power4.S +++ b/arch/powerpc/kernel/idle_power4.S @@ -53,3 +53,24 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) isync b 1b +_GLOBAL(power4_cpu_offline_powersave) + /* Go to NAP now */ + mfmsr r7 + rldicl r0,r7,48,1 + rotldi r0,r0,16 + mtmsrd r0,1 /* hard-disable interrupts */ + li r0,1 + li r6,0 + stb r0,PACAHARDIRQEN(r13) /* we'll hard-enable shortly */ + stb r6,PACASOFTIRQEN(r13) /* soft-disable irqs */ +BEGIN_FTR_SECTION + DSSALL + sync +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) + ori r7,r7,MSR_EE + oris r7,r7,MSR_POW@h + sync + isync + mtmsrd r7 + isync + blr -- cgit v1.2.3 From 55b61fec22caa3e7872caea6c4100fc75cb8f49b Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 3 May 2007 17:26:52 +1000 Subject: [POWERPC] Rename device_is_compatible to of_device_is_compatible for consistency with other Open Firmware interfaces (and Sparc). This is just a straight replacement. This leaves the compatibility define in place. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/legacy_serial.c | 14 +++++++------- arch/powerpc/kernel/of_device.c | 2 +- arch/powerpc/kernel/vio.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index 63dd2c3ad95..662cd67428d 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -243,9 +243,9 @@ static int __init add_legacy_pci_port(struct device_node *np, * doesn't work for these settings, you'll have to add your own special * cases here */ - if (device_is_compatible(pci_dev, "pci13a8,152") || - device_is_compatible(pci_dev, "pci13a8,154") || - device_is_compatible(pci_dev, "pci13a8,158")) { + if (of_device_is_compatible(pci_dev, "pci13a8,152") || + of_device_is_compatible(pci_dev, "pci13a8,154") || + of_device_is_compatible(pci_dev, "pci13a8,158")) { addr += 0x200 * lindex; base += 0x200 * lindex; } else { @@ -364,11 +364,11 @@ void __init find_legacy_serial_ports(void) /* Check for known pciclass, and also check wether we have * a device with child nodes for ports or not */ - if (device_is_compatible(np, "pciclass,0700") || - device_is_compatible(np, "pciclass,070002")) + if (of_device_is_compatible(np, "pciclass,0700") || + of_device_is_compatible(np, "pciclass,070002")) pci = np; - else if (device_is_compatible(parent, "pciclass,0700") || - device_is_compatible(parent, "pciclass,070002")) + else if (of_device_is_compatible(parent, "pciclass,0700") || + of_device_is_compatible(parent, "pciclass,070002")) pci = parent; else { of_node_put(parent); diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 0c8ea7659d9..e2c765f5f3f 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -27,7 +27,7 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches, match &= node->type && !strcmp(matches->type, node->type); if (matches->compatible[0]) - match &= device_is_compatible(node, + match &= of_device_is_compatible(node, matches->compatible); if (match) return matches; diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 9eaefac5053..ec871063733 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -117,7 +117,7 @@ static const struct vio_device_id *vio_match_device( { while (ids->type[0] != '\0') { if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) && - device_is_compatible(dev->dev.archdata.of_node, + of_device_is_compatible(dev->dev.archdata.of_node, ids->compat)) return ids; ids++; -- cgit v1.2.3 From 543b9fd3528f64c4b20439de0edb453764482de7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 3 May 2007 22:31:38 +1000 Subject: [POWERPC] powermac: Suspend to disk on G5 Powermac G5 suspend to disk implementation. The code is platform agnostic but only tested on powermac, no other 64-bit powerpc machines. Because nvidiafb still breaks suspend I have marked it EXPERIMENTAL on powermac and because I can't test it and some lowlevel code will need changes it is BROKEN on all other 64-bit platforms. Signed-off-by: Johannes Berg Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/Makefile | 1 + arch/powerpc/kernel/asm-offsets.c | 4 +- arch/powerpc/kernel/idle.c | 5 +- arch/powerpc/kernel/swsusp.c | 9 ++ arch/powerpc/kernel/swsusp_64.c | 24 ++++ arch/powerpc/kernel/swsusp_asm64.S | 228 +++++++++++++++++++++++++++++++++++++ 6 files changed, 268 insertions(+), 3 deletions(-) create mode 100644 arch/powerpc/kernel/swsusp_64.c create mode 100644 arch/powerpc/kernel/swsusp_asm64.S (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 949f36a62aa..4dc73b8c25b 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o obj-$(CONFIG_TAU) += tau_6xx.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o +obj64-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_64.o swsusp_asm64.o obj32-$(CONFIG_MODULES) += module_32.o ifeq ($(CONFIG_PPC_MERGE),y) diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 0c5150c6917..8f48560b7ee 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -21,12 +21,12 @@ #include #include #include +#include #ifdef CONFIG_PPC64 #include #include #else #include -#include #endif #include @@ -257,11 +257,11 @@ int main(void) DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore)); -#ifndef CONFIG_PPC64 DEFINE(pbe_address, offsetof(struct pbe, address)); DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); DEFINE(pbe_next, offsetof(struct pbe, next)); +#ifndef CONFIG_PPC64 DEFINE(TASK_SIZE, TASK_SIZE); DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); #endif /* ! CONFIG_PPC64 */ diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index 6e7f50967ba..a9e9cbd3297 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -33,8 +33,11 @@ #include #ifdef CONFIG_HOTPLUG_CPU +/* this is used for software suspend, and that shuts down + * CPUs even while the system is still booting... */ #define cpu_should_die() (cpu_is_offline(smp_processor_id()) && \ - system_state == SYSTEM_RUNNING) + (system_state == SYSTEM_RUNNING \ + || system_state == SYSTEM_BOOTING)) #else #define cpu_should_die() 0 #endif diff --git a/arch/powerpc/kernel/swsusp.c b/arch/powerpc/kernel/swsusp.c index b89e4f5a0b0..064a7ba4f02 100644 --- a/arch/powerpc/kernel/swsusp.c +++ b/arch/powerpc/kernel/swsusp.c @@ -24,6 +24,11 @@ void save_processor_state(void) flush_fp_to_thread(current); flush_altivec_to_thread(current); flush_spe_to_thread(current); + +#ifdef CONFIG_PPC64 + hard_irq_disable(); +#endif + } void restore_processor_state(void) @@ -31,4 +36,8 @@ void restore_processor_state(void) #ifdef CONFIG_PPC32 set_context(current->active_mm->context.id, current->active_mm->pgd); #endif + +#ifdef CONFIG_PPC64 + hard_irq_enable(); +#endif } diff --git a/arch/powerpc/kernel/swsusp_64.c b/arch/powerpc/kernel/swsusp_64.c new file mode 100644 index 00000000000..6f3f0697274 --- /dev/null +++ b/arch/powerpc/kernel/swsusp_64.c @@ -0,0 +1,24 @@ +/* + * PowerPC 64-bit swsusp implementation + * + * Copyright 2006 Johannes Berg + * + * GPLv2 + */ + +#include +#include +#include +#include + +void do_after_copyback(void) +{ + iommu_restore(); + touch_softlockup_watchdog(); + mb(); +} + +void _iommu_save(void) +{ + iommu_save(); +} diff --git a/arch/powerpc/kernel/swsusp_asm64.S b/arch/powerpc/kernel/swsusp_asm64.S new file mode 100644 index 00000000000..e092c3cbdb9 --- /dev/null +++ b/arch/powerpc/kernel/swsusp_asm64.S @@ -0,0 +1,228 @@ +/* + * PowerPC 64-bit swsusp implementation + * + * Copyright 2006 Johannes Berg + * + * GPLv2 + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Structure for storing CPU registers on the save area. + */ +#define SL_r1 0x00 /* stack pointer */ +#define SL_PC 0x08 +#define SL_MSR 0x10 +#define SL_SDR1 0x18 +#define SL_XER 0x20 +#define SL_TB 0x40 +#define SL_r2 0x48 +#define SL_CR 0x50 +#define SL_LR 0x58 +#define SL_r12 0x60 +#define SL_r13 0x68 +#define SL_r14 0x70 +#define SL_r15 0x78 +#define SL_r16 0x80 +#define SL_r17 0x88 +#define SL_r18 0x90 +#define SL_r19 0x98 +#define SL_r20 0xa0 +#define SL_r21 0xa8 +#define SL_r22 0xb0 +#define SL_r23 0xb8 +#define SL_r24 0xc0 +#define SL_r25 0xc8 +#define SL_r26 0xd0 +#define SL_r27 0xd8 +#define SL_r28 0xe0 +#define SL_r29 0xe8 +#define SL_r30 0xf0 +#define SL_r31 0xf8 +#define SL_SIZE SL_r31+8 + +/* these macros rely on the save area being + * pointed to by r11 */ +#define SAVE_SPECIAL(special) \ + mf##special r0 ;\ + std r0, SL_##special(r11) +#define RESTORE_SPECIAL(special) \ + ld r0, SL_##special(r11) ;\ + mt##special r0 +#define SAVE_REGISTER(reg) \ + std reg, SL_##reg(r11) +#define RESTORE_REGISTER(reg) \ + ld reg, SL_##reg(r11) + +/* space for storing cpu state */ + .section .data + .align 5 +swsusp_save_area: + .space SL_SIZE + + .section ".toc","aw" +swsusp_save_area_ptr: + .tc swsusp_save_area[TC],swsusp_save_area +restore_pblist_ptr: + .tc restore_pblist[TC],restore_pblist + + .section .text + .align 5 +_GLOBAL(swsusp_arch_suspend) + ld r11,swsusp_save_area_ptr@toc(r2) + SAVE_SPECIAL(LR) + SAVE_REGISTER(r1) + SAVE_SPECIAL(CR) + SAVE_SPECIAL(TB) + SAVE_REGISTER(r2) + SAVE_REGISTER(r12) + SAVE_REGISTER(r13) + SAVE_REGISTER(r14) + SAVE_REGISTER(r15) + SAVE_REGISTER(r16) + SAVE_REGISTER(r17) + SAVE_REGISTER(r18) + SAVE_REGISTER(r19) + SAVE_REGISTER(r20) + SAVE_REGISTER(r21) + SAVE_REGISTER(r22) + SAVE_REGISTER(r23) + SAVE_REGISTER(r24) + SAVE_REGISTER(r25) + SAVE_REGISTER(r26) + SAVE_REGISTER(r27) + SAVE_REGISTER(r28) + SAVE_REGISTER(r29) + SAVE_REGISTER(r30) + SAVE_REGISTER(r31) + SAVE_SPECIAL(MSR) + SAVE_SPECIAL(SDR1) + SAVE_SPECIAL(XER) + + /* we push the stack up 128 bytes but don't store the + * stack pointer on the stack like a real stackframe */ + addi r1,r1,-128 + + bl _iommu_save + bl swsusp_save + + /* restore LR */ + ld r11,swsusp_save_area_ptr@toc(r2) + RESTORE_SPECIAL(LR) + addi r1,r1,128 + + blr + +/* Resume code */ +_GLOBAL(swsusp_arch_resume) + /* Stop pending alitvec streams and memory accesses */ +BEGIN_FTR_SECTION + DSSALL +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) + sync + + ld r12,restore_pblist_ptr@toc(r2) + ld r12,0(r12) + + cmpdi r12,0 + beq- nothing_to_copy + li r15,512 +copyloop: + ld r13,pbe_address(r12) + ld r14,pbe_orig_address(r12) + + mtctr r15 + li r10,0 +copy_page_loop: + ldx r0,r10,r13 + stdx r0,r10,r14 + addi r10,r10,8 + bdnz copy_page_loop + + ld r12,pbe_next(r12) + cmpdi r12,0 + bne+ copyloop +nothing_to_copy: + + /* flush caches */ + lis r3, 0x10 + mtctr r3 + li r3, 0 + ori r3, r3, CONFIG_KERNEL_START>>48 + li r0, 48 + sld r3, r3, r0 + li r0, 0 +1: + dcbf r0,r3 + addi r3,r3,0x20 + bdnz 1b + + sync + + tlbia + + ld r11,swsusp_save_area_ptr@toc(r2) + + RESTORE_SPECIAL(CR) + + /* restore timebase */ + /* load saved tb */ + ld r1, SL_TB(r11) + /* get upper 32 bits of it */ + srdi r2, r1, 32 + /* clear tb lower to avoid wrap */ + li r0, 0 + mttbl r0 + /* set tb upper */ + mttbu r2 + /* set tb lower */ + mttbl r1 + + /* restore registers */ + RESTORE_REGISTER(r1) + RESTORE_REGISTER(r2) + RESTORE_REGISTER(r12) + RESTORE_REGISTER(r13) + RESTORE_REGISTER(r14) + RESTORE_REGISTER(r15) + RESTORE_REGISTER(r16) + RESTORE_REGISTER(r17) + RESTORE_REGISTER(r18) + RESTORE_REGISTER(r19) + RESTORE_REGISTER(r20) + RESTORE_REGISTER(r21) + RESTORE_REGISTER(r22) + RESTORE_REGISTER(r23) + RESTORE_REGISTER(r24) + RESTORE_REGISTER(r25) + RESTORE_REGISTER(r26) + RESTORE_REGISTER(r27) + RESTORE_REGISTER(r28) + RESTORE_REGISTER(r29) + RESTORE_REGISTER(r30) + RESTORE_REGISTER(r31) + /* can't use RESTORE_SPECIAL(MSR) */ + ld r0, SL_MSR(r11) + mtmsrd r0, 0 + RESTORE_SPECIAL(SDR1) + RESTORE_SPECIAL(XER) + + sync + + addi r1,r1,-128 + bl slb_flush_and_rebolt + bl do_after_copyback + addi r1,r1,128 + + ld r11,swsusp_save_area_ptr@toc(r2) + RESTORE_SPECIAL(LR) + + li r3, 0 + blr -- cgit v1.2.3 From de41189bf6838c1c885d360e5cdf7ec6b4d336d6 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Mon, 7 May 2007 01:38:46 +1000 Subject: [POWERPC] Export of_device_get_modalias Apparently other parts of the kernel need to know the modalias internally (like the sysfs code in macintosh driver). To avoid consistency issues, we export this code and use it everywhere it's needed rather than repeat it ... Signed-off-by: Sylvain Munaut Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/of_device.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index e2c765f5f3f..a464d67248d 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -120,8 +120,8 @@ void of_device_unregister(struct of_device *ofdev) } -static ssize_t of_device_get_modalias(struct of_device *ofdev, - char *str, ssize_t len) +ssize_t of_device_get_modalias(struct of_device *ofdev, + char *str, ssize_t len) { const char *compat; int cplen, i; @@ -239,3 +239,4 @@ EXPORT_SYMBOL(of_dev_get); EXPORT_SYMBOL(of_dev_put); EXPORT_SYMBOL(of_release_dev); EXPORT_SYMBOL(of_device_uevent); +EXPORT_SYMBOL(of_device_get_modalias); -- cgit v1.2.3 From 3a5cc44268d9c3eee301f366801005e331b1e871 Mon Sep 17 00:00:00 2001 From: Domen Puncer Date: Mon, 7 May 2007 01:38:50 +1000 Subject: [POWERPC] Set efika's device_type to "soc" Device type should be "soc" (as in lite5200.dts), compatible is already set to "mpc5200". Signed-off-by: Domen Puncer Signed-off-by: Sylvain Munaut Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index e27d9d1b6e6..87efb42247d 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -2153,7 +2153,7 @@ static void __init fixup_device_tree_efika(void) 3,12,0, 3,13,0, 3,14,0, 3,15,0 }; struct subst_entry efika_subst_table[] = { { "/", "device_type", prop_cstr("efika") }, - { "/builtin", "compatible", prop_cstr("soc") }, + { "/builtin", "device_type", prop_cstr("soc") }, { "/builtin/ata", "compatible", prop_cstr("mpc5200b-ata\0mpc5200-ata"), }, { "/builtin/bestcomm", "compatible", prop_cstr("mpc5200b-bestcomm\0mpc5200-bestcomm") }, { "/builtin/bestcomm", "interrupts", prop_bcomm_irq, sizeof(prop_bcomm_irq) }, -- cgit v1.2.3 From 11fbb00c67e19737757e747ec7dd3ba8d584f5d1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 7 May 2007 15:16:23 +1000 Subject: [POWERPC] Cope with PCI host bridge I/O window not starting at 0 Currently our code to set up the data structures for a PCI host bridge and create the mapping for its I/O window assumes that the window starts at I/O port 0 on the PCI side. If this is not true, we can end up with I/O port numbers in the resources for PCI devices which will cause an oops if a driver tries to access them via inb/outb etc., because there is no mapping for the corresponding addresses. Normally the I/O window starts at 0, but there are some situations on partitioned machines with a hypervisor where the window may not start at 0. This fixes the problem by allocating space for the range from 0 to the end of the I/O window. That is, hose->io_base_virt contains the virtual address for I/O port 0 on the PCI bus, and thus the assumption that hose->io_base_virt - pci_io_base is the offset between the "global" I/O port numbers (those in the PCI device resources) and the I/O port numbers on the PCI bus is maintained. For PCI host bridges that are present at boot, we only map the portion of that range that correspond to the bridge's I/O window. For bridges added after boot we ioremap the range from 0 to the end of the I/O window, for now; in fact hot-added bridges should be using reserve_phb_iospace() and __ioremap_explicit (so they get sensible global port numbers), but we don't have the infrastructure yet to do that (basically a free_phb_iospace() routine plus appropriate locking). Interestingly, this makes the two arms of the if statement in get_bus_io_range do almost exactly the same thing; that function could now be simplified in a further patch. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 60d7d4baa22..706b7f3da5f 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -1006,8 +1006,9 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, switch ((pci_space >> 24) & 0x3) { case 1: /* I/O space */ - hose->io_base_phys = cpu_phys_addr; - hose->pci_io_size = size; + hose->io_base_phys = cpu_phys_addr - pci_addr; + /* handle from 0 to top of I/O window */ + hose->pci_io_size = pci_addr + size; res = &hose->io_resource; res->flags = IORESOURCE_IO; @@ -1117,8 +1118,8 @@ static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys, } else { /* Root Bus */ res = &hose->io_resource; - *start_phys = hose->io_base_phys; - *start_virt = (unsigned long) hose->io_base_virt; + *start_phys = hose->io_base_phys + res->start; + *start_virt = (unsigned long) hose->io_base_virt + res->start; if (res->end > res->start) *size = res->end - res->start + 1; else { -- cgit v1.2.3 From 0108d3fe3c44f01de224f39347b95f6a94181687 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 7 May 2007 15:58:28 +1000 Subject: [POWERPC] Add __init annotations to reserve_mem() and stabs_alloc() reserve_mem() and stabs_alloc() are both called only from other __init routines, so can be marked __init. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 87efb42247d..eee3555ced7 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -967,7 +967,7 @@ static unsigned long __init prom_next_cell(int s, cell_t **cellp) * If problems seem to show up, it would be a good start to track * them down. */ -static void reserve_mem(u64 base, u64 size) +static void __init reserve_mem(u64 base, u64 size) { u64 top = base + size; unsigned long cnt = RELOC(mem_reserve_cnt); -- cgit v1.2.3 From f728b5c3a599d0410a079f447f921a10be7d59d6 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 8 May 2007 12:58:33 +1000 Subject: [POWERPC] Rip out the existing powerpc msi stubs Rip out the existing powerpc msi stubs. These were the start of an implementation based on ppc_md calls, but were never used in mainline. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/irq.c | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 5719a530f2d..9ed4931af16 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -958,33 +958,6 @@ arch_initcall(irq_late_init); #endif /* CONFIG_PPC_MERGE */ -#ifdef CONFIG_PCI_MSI -int pci_enable_msi(struct pci_dev * pdev) -{ - if (ppc_md.enable_msi) - return ppc_md.enable_msi(pdev); - else - return -1; -} -EXPORT_SYMBOL(pci_enable_msi); - -void pci_disable_msi(struct pci_dev * pdev) -{ - if (ppc_md.disable_msi) - ppc_md.disable_msi(pdev); -} -EXPORT_SYMBOL(pci_disable_msi); - -void pci_scan_msi_device(struct pci_dev *dev) {} -int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) {return -1;} -void pci_disable_msix(struct pci_dev *dev) {} -void msi_remove_pci_irq_vectors(struct pci_dev *dev) {} -void pci_no_msi(void) {} -EXPORT_SYMBOL(pci_enable_msix); -EXPORT_SYMBOL(pci_disable_msix); - -#endif - #ifdef CONFIG_PPC64 static int __init setup_noirqdistrib(char *str) { -- cgit v1.2.3 From df87ef5508b40fc655b6c4771be31741d8ec1596 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 8 May 2007 12:58:34 +1000 Subject: [POWERPC] PowerPC MSI infrastructure This provides the architecture specific hooks to support MSI on powerpc. We implement the newly added arch_setup_msi_irqs() and arch_teardown_msi_irqs(), and then delegate to ppc_md routines. Platforms that don't implement MSI will leave the ppc_md calls blank, arch_msi_check_device() will detect this and return ENOSYS. Drivers should detect this error and continue to use LSI. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/Makefile | 1 + arch/powerpc/kernel/msi.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 arch/powerpc/kernel/msi.c (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 94c703a9501..3e779f07f21 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_MODULES) += $(module-y) pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci32-$(CONFIG_PPC32) := pci_32.o obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) +obj-$(CONFIG_PCI_MSI) += msi.o kexec-$(CONFIG_PPC64) := machine_kexec_64.o kexec-$(CONFIG_PPC32) := machine_kexec_32.o obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y) diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c new file mode 100644 index 00000000000..c62d1012c01 --- /dev/null +++ b/arch/powerpc/kernel/msi.c @@ -0,0 +1,38 @@ +/* + * Copyright 2006-2007, Michael Ellerman, IBM Corporation. + * + * 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 +#include + +#include + +int arch_msi_check_device(struct pci_dev* dev, int nvec, int type) +{ + if (!ppc_md.setup_msi_irqs || !ppc_md.teardown_msi_irqs) { + pr_debug("msi: Platform doesn't provide MSI callbacks.\n"); + return -ENOSYS; + } + + if (ppc_md.msi_check_device) { + pr_debug("msi: Using platform check routine.\n"); + return ppc_md.msi_check_device(dev, nvec, type); + } + + return 0; +} + +int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +{ + return ppc_md.setup_msi_irqs(dev, nvec, type); +} + +void arch_teardown_msi_irqs(struct pci_dev *dev) +{ + return ppc_md.teardown_msi_irqs(dev); +} -- cgit v1.2.3 From 014dad902aad6f5efbd65d0524b2e99304d2b07e Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 8 May 2007 12:58:35 +1000 Subject: [POWERPC] Tell Phyp we support MSI Tell Phyp we support MSI via the client architecture support mechanism. Signed-off-by: Jake Moilanen Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_init.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index eee3555ced7..d6047c44103 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -635,6 +635,12 @@ static void __init early_cmdline_parse(void) /* ibm,dynamic-reconfiguration-memory property supported */ #define OV5_DRCONF_MEMORY 0x20 #define OV5_LARGE_PAGES 0x10 /* large pages supported */ +/* PCIe/MSI support. Without MSI full PCIe is not supported */ +#ifdef CONFIG_PCI_MSI +#define OV5_MSI 0x01 /* PCIe/MSI support */ +#else +#define OV5_MSI 0x00 +#endif /* CONFIG_PCI_MSI */ /* * The architecture vector has an array of PVR mask/value pairs, @@ -679,7 +685,7 @@ static unsigned char ibm_architecture_vec[] = { /* option vector 5: PAPR/OF options */ 3 - 2, /* length */ 0, /* don't ignore, don't halt */ - OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY, + OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI, }; /* Old method - ELF header with PT_NOTE sections */ -- cgit v1.2.3 From 2cd976477035716af52a6eff6625f32e5813c02b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 May 2007 12:59:30 +1000 Subject: [POWERPC] Add powerpc/platforms/44x, disable platforms/4xx for now This prepares for Ebony/440 support by creating an arch/powerpc/platforms/44x directory. It is populated with a single misc_44x.S file, into which is moved the 44x specific reset code from head_44x.S (on the grounds that we should really stop clogging up the head_* files with random asm helper routines). At the same time, we disable the (empty save Kconfig and Makefile) arch/powerpc/platforms/4xx directory from the arch/powerpc/platforms Makefile. Contrary to the comment in arch/powerpc/platforms/4xx/Makefile, attempting to build such an empty Makefile will fail, thus breaking compile for the 44x platforms we're about to add. It can go back in once we start porting some of the 40x platforms (and thus it becomes non-empty). Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/head_44x.S | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index 9ee6773cf02..a51026f0a9d 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -709,16 +709,6 @@ _GLOBAL(giveup_fpu) blr #endif -/* - * extern void abort(void) - * - * At present, this routine just applies a system reset. - */ -_GLOBAL(abort) - mfspr r13,SPRN_DBCR0 - oris r13,r13,DBCR0_RST_SYSTEM@h - mtspr SPRN_DBCR0,r13 - _GLOBAL(set_context) #ifdef CONFIG_BDI_SWITCH -- cgit v1.2.3 From d9b55a03611ff2e2e54fb4e1ad2648d5eb870fa3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 May 2007 12:59:31 +1000 Subject: [POWERPC] Early serial debug support for PPC44x This adds support for early serial debugging via the built in port on IBM/AMCC PowerPC 44x CPUs. It uses a bolted TLB entry in address space 1 for the UART's mapping, allowing robust debugging both before and after the initialization of the MMU. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/head_44x.S | 34 +++++++++++++--------------------- arch/powerpc/kernel/of_platform.c | 1 - arch/powerpc/kernel/udbg.c | 3 +++ arch/powerpc/kernel/udbg_16550.c | 23 +++++++++++++++++++++++ 4 files changed, 39 insertions(+), 22 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index a51026f0a9d..88695963f58 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -172,36 +172,28 @@ skpinv: addi r4,r4,1 /* Increment */ isync 4: -#ifdef CONFIG_SERIAL_TEXT_DEBUG - /* - * Add temporary UART mapping for early debug. - * We can map UART registers wherever we want as long as they don't - * interfere with other system mappings (e.g. with pinned entries). - * For an example of how we handle this - see ocotea.h. --ebs - */ +#ifdef CONFIG_PPC_EARLY_DEBUG_44x + /* Add UART mapping for early debug. */ + /* pageid fields */ - lis r3,UART0_IO_BASE@h - ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_4K + lis r3,PPC44x_EARLY_DEBUG_VIRTADDR@h + ori r3,r3,PPC44x_TLB_VALID|PPC44x_TLB_TS|PPC44x_TLB_64K /* xlat fields */ - lis r4,UART0_PHYS_IO_BASE@h /* RPN depends on SoC */ -#ifndef CONFIG_440EP - ori r4,r4,0x0001 /* ERPN is 1 for second 4GB page */ -#endif + lis r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW@h + ori r4,r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH /* attrib fields */ - li r5,0 - ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G) + li r5,(PPC44x_TLB_SW|PPC44x_TLB_SR|PPC44x_TLB_I|PPC44x_TLB_G) + li r0,62 /* TLB slot 0 */ - li r0,0 /* TLB slot 0 */ - - tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ - tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ - tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */ + tlbwe r3,r0,PPC44x_TLB_PAGEID + tlbwe r4,r0,PPC44x_TLB_XLAT + tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Force context change */ isync -#endif /* CONFIG_SERIAL_TEXT_DEBUG */ +#endif /* CONFIG_PPC_EARLY_DEBUG_44x */ /* Establish the interrupt vector offsets */ SET_IVOR(0, CriticalInput); diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 908ed7926db..84c34d979a8 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -29,7 +29,6 @@ #include #include - /* * The list of OF IDs below is used for matching bus types in the * system whose devices are to be exposed as of_platform_devices. diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 7e0971868fc..7ef97ea8b3e 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c @@ -51,6 +51,9 @@ void __init udbg_early_init(void) udbg_init_pas_realmode(); #elif defined(CONFIG_BOOTX_TEXT) udbg_init_btext(); +#elif defined(CONFIG_PPC_EARLY_DEBUG_44x) + /* PPC44x debug */ + udbg_init_44x_as1(); #endif } diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index a963f657222..7afab5bcd61 100644 --- a/arch/powerpc/kernel/udbg_16550.c +++ b/arch/powerpc/kernel/udbg_16550.c @@ -191,3 +191,26 @@ void udbg_init_pas_realmode(void) udbg_getc_poll = NULL; } #endif /* CONFIG_PPC_MAPLE */ + +#ifdef CONFIG_PPC_EARLY_DEBUG_44x +#include + +static void udbg_44x_as1_putc(char c) +{ + if (udbg_comport) { + while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0) + /* wait for idle */; + as1_writeb(c, &udbg_comport->thr); eieio(); + if (c == '\n') + udbg_44x_as1_putc('\r'); + } +} + +void __init udbg_init_44x_as1(void) +{ + udbg_comport = + (volatile struct NS16550 __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR; + + udbg_putc = udbg_44x_as1_putc; +} +#endif /* CONFIG_PPC_EARLY_DEBUG_44x */ -- cgit v1.2.3