diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:50:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:50:19 -0400 |
commit | df6d3916f3b7b7e2067567a256dd4f0c1ea854a2 (patch) | |
tree | 0fdeab1ab5d566605fc99aeb5ea3f621f11e7608 /arch/powerpc/kernel | |
parent | 74add80cbd7fe246c893b93ee75ac59acdd01dd4 (diff) | |
parent | 197686dfe0038fd190326d118b743ff65ad20c0e (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (77 commits)
[POWERPC] Abolish powerpc_flash_init()
[POWERPC] Early serial debug support for PPC44x
[POWERPC] Support for the Ebony 440GP reference board in arch/powerpc
[POWERPC] Add device tree for Ebony
[POWERPC] Add powerpc/platforms/44x, disable platforms/4xx for now
[POWERPC] MPIC U3/U4 MSI backend
[POWERPC] MPIC MSI allocator
[POWERPC] Enable MSI mappings for MPIC
[POWERPC] Tell Phyp we support MSI
[POWERPC] RTAS MSI implementation
[POWERPC] PowerPC MSI infrastructure
[POWERPC] Rip out the existing powerpc msi stubs
[POWERPC] Remove use of 4level-fixup.h for ppc32
[POWERPC] Add powerpc PCI-E reset API implementation
[POWERPC] Holly bootwrapper
[POWERPC] Holly DTS
[POWERPC] Holly defconfig
[POWERPC] Add support for 750CL Holly board
[POWERPC] Generalize tsi108 PCI setup
[POWERPC] Generalize tsi108 PHY types
...
Fixed conflict in include/asm-powerpc/kdebug.h manually
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/powerpc/kernel')
24 files changed, 521 insertions, 116 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index aa693d0f151a..3e779f07f21b 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -36,8 +36,9 @@ obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o | |||
36 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 36 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
37 | obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o | 37 | obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o |
38 | obj-$(CONFIG_TAU) += tau_6xx.o | 38 | obj-$(CONFIG_TAU) += tau_6xx.o |
39 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o suspend.o | ||
39 | obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o | 40 | obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o |
40 | obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o | 41 | obj64-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_64.o swsusp_asm64.o |
41 | obj32-$(CONFIG_MODULES) += module_32.o | 42 | obj32-$(CONFIG_MODULES) += module_32.o |
42 | 43 | ||
43 | ifeq ($(CONFIG_PPC_MERGE),y) | 44 | ifeq ($(CONFIG_PPC_MERGE),y) |
@@ -67,6 +68,7 @@ obj-$(CONFIG_MODULES) += $(module-y) | |||
67 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o | 68 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o |
68 | pci32-$(CONFIG_PPC32) := pci_32.o | 69 | pci32-$(CONFIG_PPC32) := pci_32.o |
69 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) | 70 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) |
71 | obj-$(CONFIG_PCI_MSI) += msi.o | ||
70 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o | 72 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o |
71 | kexec-$(CONFIG_PPC32) := machine_kexec_32.o | 73 | kexec-$(CONFIG_PPC32) := machine_kexec_32.o |
72 | obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y) | 74 | obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y) |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 0c5150c69175..8f48560b7ee2 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -21,12 +21,12 @@ | |||
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/mman.h> | 22 | #include <linux/mman.h> |
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/suspend.h> | ||
24 | #ifdef CONFIG_PPC64 | 25 | #ifdef CONFIG_PPC64 |
25 | #include <linux/time.h> | 26 | #include <linux/time.h> |
26 | #include <linux/hardirq.h> | 27 | #include <linux/hardirq.h> |
27 | #else | 28 | #else |
28 | #include <linux/ptrace.h> | 29 | #include <linux/ptrace.h> |
29 | #include <linux/suspend.h> | ||
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | #include <asm/io.h> | 32 | #include <asm/io.h> |
@@ -257,11 +257,11 @@ int main(void) | |||
257 | DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); | 257 | DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); |
258 | DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore)); | 258 | DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore)); |
259 | 259 | ||
260 | #ifndef CONFIG_PPC64 | ||
261 | DEFINE(pbe_address, offsetof(struct pbe, address)); | 260 | DEFINE(pbe_address, offsetof(struct pbe, address)); |
262 | DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); | 261 | DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); |
263 | DEFINE(pbe_next, offsetof(struct pbe, next)); | 262 | DEFINE(pbe_next, offsetof(struct pbe, next)); |
264 | 263 | ||
264 | #ifndef CONFIG_PPC64 | ||
265 | DEFINE(TASK_SIZE, TASK_SIZE); | 265 | DEFINE(TASK_SIZE, TASK_SIZE); |
266 | DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); | 266 | DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); |
267 | #endif /* ! CONFIG_PPC64 */ | 267 | #endif /* ! CONFIG_PPC64 */ |
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index a15d4b8cce48..88695963f587 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 */ | |||
120 | * Configure and load pinned entry into TLB slot 63. | 120 | * Configure and load pinned entry into TLB slot 63. |
121 | */ | 121 | */ |
122 | 122 | ||
123 | lis r3,KERNELBASE@h /* Load the kernel virtual address */ | 123 | lis r3,PAGE_OFFSET@h |
124 | ori r3,r3,KERNELBASE@l | 124 | ori r3,r3,PAGE_OFFSET@l |
125 | 125 | ||
126 | /* Kernel is at the base of RAM */ | 126 | /* Kernel is at the base of RAM */ |
127 | li r4, 0 /* Load the kernel physical address */ | 127 | li r4, 0 /* Load the kernel physical address */ |
@@ -172,36 +172,28 @@ skpinv: addi r4,r4,1 /* Increment */ | |||
172 | isync | 172 | isync |
173 | 173 | ||
174 | 4: | 174 | 4: |
175 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | 175 | #ifdef CONFIG_PPC_EARLY_DEBUG_44x |
176 | /* | 176 | /* Add UART mapping for early debug. */ |
177 | * Add temporary UART mapping for early debug. | 177 | |
178 | * We can map UART registers wherever we want as long as they don't | ||
179 | * interfere with other system mappings (e.g. with pinned entries). | ||
180 | * For an example of how we handle this - see ocotea.h. --ebs | ||
181 | */ | ||
182 | /* pageid fields */ | 178 | /* pageid fields */ |
183 | lis r3,UART0_IO_BASE@h | 179 | lis r3,PPC44x_EARLY_DEBUG_VIRTADDR@h |
184 | ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_4K | 180 | ori r3,r3,PPC44x_TLB_VALID|PPC44x_TLB_TS|PPC44x_TLB_64K |
185 | 181 | ||
186 | /* xlat fields */ | 182 | /* xlat fields */ |
187 | lis r4,UART0_PHYS_IO_BASE@h /* RPN depends on SoC */ | 183 | lis r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW@h |
188 | #ifndef CONFIG_440EP | 184 | ori r4,r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH |
189 | ori r4,r4,0x0001 /* ERPN is 1 for second 4GB page */ | ||
190 | #endif | ||
191 | 185 | ||
192 | /* attrib fields */ | 186 | /* attrib fields */ |
193 | li r5,0 | 187 | li r5,(PPC44x_TLB_SW|PPC44x_TLB_SR|PPC44x_TLB_I|PPC44x_TLB_G) |
194 | ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G) | 188 | li r0,62 /* TLB slot 0 */ |
195 | 189 | ||
196 | li r0,0 /* TLB slot 0 */ | 190 | tlbwe r3,r0,PPC44x_TLB_PAGEID |
197 | 191 | tlbwe r4,r0,PPC44x_TLB_XLAT | |
198 | tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ | 192 | tlbwe r5,r0,PPC44x_TLB_ATTRIB |
199 | tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ | ||
200 | tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */ | ||
201 | 193 | ||
202 | /* Force context change */ | 194 | /* Force context change */ |
203 | isync | 195 | isync |
204 | #endif /* CONFIG_SERIAL_TEXT_DEBUG */ | 196 | #endif /* CONFIG_PPC_EARLY_DEBUG_44x */ |
205 | 197 | ||
206 | /* Establish the interrupt vector offsets */ | 198 | /* Establish the interrupt vector offsets */ |
207 | SET_IVOR(0, CriticalInput); | 199 | SET_IVOR(0, CriticalInput); |
@@ -709,16 +701,6 @@ _GLOBAL(giveup_fpu) | |||
709 | blr | 701 | blr |
710 | #endif | 702 | #endif |
711 | 703 | ||
712 | /* | ||
713 | * extern void abort(void) | ||
714 | * | ||
715 | * At present, this routine just applies a system reset. | ||
716 | */ | ||
717 | _GLOBAL(abort) | ||
718 | mfspr r13,SPRN_DBCR0 | ||
719 | oris r13,r13,DBCR0_RST_SYSTEM@h | ||
720 | mtspr SPRN_DBCR0,r13 | ||
721 | |||
722 | _GLOBAL(set_context) | 704 | _GLOBAL(set_context) |
723 | 705 | ||
724 | #ifdef CONFIG_BDI_SWITCH | 706 | #ifdef CONFIG_BDI_SWITCH |
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index 6e7f50967bab..a9e9cbd32975 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c | |||
@@ -33,8 +33,11 @@ | |||
33 | #include <asm/smp.h> | 33 | #include <asm/smp.h> |
34 | 34 | ||
35 | #ifdef CONFIG_HOTPLUG_CPU | 35 | #ifdef CONFIG_HOTPLUG_CPU |
36 | /* this is used for software suspend, and that shuts down | ||
37 | * CPUs even while the system is still booting... */ | ||
36 | #define cpu_should_die() (cpu_is_offline(smp_processor_id()) && \ | 38 | #define cpu_should_die() (cpu_is_offline(smp_processor_id()) && \ |
37 | system_state == SYSTEM_RUNNING) | 39 | (system_state == SYSTEM_RUNNING \ |
40 | || system_state == SYSTEM_BOOTING)) | ||
38 | #else | 41 | #else |
39 | #define cpu_should_die() 0 | 42 | #define cpu_should_die() 0 |
40 | #endif | 43 | #endif |
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S index ba3195478600..5328709eeedc 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) | |||
53 | isync | 53 | isync |
54 | b 1b | 54 | b 1b |
55 | 55 | ||
56 | _GLOBAL(power4_cpu_offline_powersave) | ||
57 | /* Go to NAP now */ | ||
58 | mfmsr r7 | ||
59 | rldicl r0,r7,48,1 | ||
60 | rotldi r0,r0,16 | ||
61 | mtmsrd r0,1 /* hard-disable interrupts */ | ||
62 | li r0,1 | ||
63 | li r6,0 | ||
64 | stb r0,PACAHARDIRQEN(r13) /* we'll hard-enable shortly */ | ||
65 | stb r6,PACASOFTIRQEN(r13) /* soft-disable irqs */ | ||
66 | BEGIN_FTR_SECTION | ||
67 | DSSALL | ||
68 | sync | ||
69 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
70 | ori r7,r7,MSR_EE | ||
71 | oris r7,r7,MSR_POW@h | ||
72 | sync | ||
73 | isync | ||
74 | mtmsrd r7 | ||
75 | isync | ||
76 | blr | ||
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 6c83fe229e60..9ed4931af164 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -67,6 +67,7 @@ | |||
67 | #ifdef CONFIG_PPC64 | 67 | #ifdef CONFIG_PPC64 |
68 | #include <asm/paca.h> | 68 | #include <asm/paca.h> |
69 | #include <asm/firmware.h> | 69 | #include <asm/firmware.h> |
70 | #include <asm/lv1call.h> | ||
70 | #endif | 71 | #endif |
71 | 72 | ||
72 | int __irq_offset_value; | 73 | int __irq_offset_value; |
@@ -162,6 +163,16 @@ void local_irq_restore(unsigned long en) | |||
162 | local_paca->hard_enabled = en; | 163 | local_paca->hard_enabled = en; |
163 | if ((int)mfspr(SPRN_DEC) < 0) | 164 | if ((int)mfspr(SPRN_DEC) < 0) |
164 | mtspr(SPRN_DEC, 1); | 165 | mtspr(SPRN_DEC, 1); |
166 | |||
167 | /* | ||
168 | * Force the delivery of pending soft-disabled interrupts on PS3. | ||
169 | * Any HV call will have this side effect. | ||
170 | */ | ||
171 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) { | ||
172 | u64 tmp; | ||
173 | lv1_get_version_info(&tmp); | ||
174 | } | ||
175 | |||
165 | hard_irq_enable(); | 176 | hard_irq_enable(); |
166 | } | 177 | } |
167 | #endif /* CONFIG_PPC64 */ | 178 | #endif /* CONFIG_PPC64 */ |
@@ -947,33 +958,6 @@ arch_initcall(irq_late_init); | |||
947 | 958 | ||
948 | #endif /* CONFIG_PPC_MERGE */ | 959 | #endif /* CONFIG_PPC_MERGE */ |
949 | 960 | ||
950 | #ifdef CONFIG_PCI_MSI | ||
951 | int pci_enable_msi(struct pci_dev * pdev) | ||
952 | { | ||
953 | if (ppc_md.enable_msi) | ||
954 | return ppc_md.enable_msi(pdev); | ||
955 | else | ||
956 | return -1; | ||
957 | } | ||
958 | EXPORT_SYMBOL(pci_enable_msi); | ||
959 | |||
960 | void pci_disable_msi(struct pci_dev * pdev) | ||
961 | { | ||
962 | if (ppc_md.disable_msi) | ||
963 | ppc_md.disable_msi(pdev); | ||
964 | } | ||
965 | EXPORT_SYMBOL(pci_disable_msi); | ||
966 | |||
967 | void pci_scan_msi_device(struct pci_dev *dev) {} | ||
968 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) {return -1;} | ||
969 | void pci_disable_msix(struct pci_dev *dev) {} | ||
970 | void msi_remove_pci_irq_vectors(struct pci_dev *dev) {} | ||
971 | void pci_no_msi(void) {} | ||
972 | EXPORT_SYMBOL(pci_enable_msix); | ||
973 | EXPORT_SYMBOL(pci_disable_msix); | ||
974 | |||
975 | #endif | ||
976 | |||
977 | #ifdef CONFIG_PPC64 | 961 | #ifdef CONFIG_PPC64 |
978 | static int __init setup_noirqdistrib(char *str) | 962 | static int __init setup_noirqdistrib(char *str) |
979 | { | 963 | { |
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 088b8c6defa0..0c96611f02f4 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
@@ -401,7 +401,7 @@ out: | |||
401 | return 1; | 401 | return 1; |
402 | } | 402 | } |
403 | 403 | ||
404 | static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | 404 | int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) |
405 | { | 405 | { |
406 | struct kprobe *cur = kprobe_running(); | 406 | struct kprobe *cur = kprobe_running(); |
407 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 407 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
@@ -486,14 +486,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
486 | if (post_kprobe_handler(args->regs)) | 486 | if (post_kprobe_handler(args->regs)) |
487 | ret = NOTIFY_STOP; | 487 | ret = NOTIFY_STOP; |
488 | break; | 488 | break; |
489 | case DIE_PAGE_FAULT: | ||
490 | /* kprobe_running() needs smp_processor_id() */ | ||
491 | preempt_disable(); | ||
492 | if (kprobe_running() && | ||
493 | kprobe_fault_handler(args->regs, args->trapnr)) | ||
494 | ret = NOTIFY_STOP; | ||
495 | preempt_enable(); | ||
496 | break; | ||
497 | default: | 489 | default: |
498 | break; | 490 | break; |
499 | } | 491 | } |
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index ae4836ea7442..cea8045ba40b 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c | |||
@@ -244,9 +244,9 @@ static int __init add_legacy_pci_port(struct device_node *np, | |||
244 | * doesn't work for these settings, you'll have to add your own special | 244 | * doesn't work for these settings, you'll have to add your own special |
245 | * cases here | 245 | * cases here |
246 | */ | 246 | */ |
247 | if (device_is_compatible(pci_dev, "pci13a8,152") || | 247 | if (of_device_is_compatible(pci_dev, "pci13a8,152") || |
248 | device_is_compatible(pci_dev, "pci13a8,154") || | 248 | of_device_is_compatible(pci_dev, "pci13a8,154") || |
249 | device_is_compatible(pci_dev, "pci13a8,158")) { | 249 | of_device_is_compatible(pci_dev, "pci13a8,158")) { |
250 | addr += 0x200 * lindex; | 250 | addr += 0x200 * lindex; |
251 | base += 0x200 * lindex; | 251 | base += 0x200 * lindex; |
252 | } else { | 252 | } else { |
@@ -365,11 +365,11 @@ void __init find_legacy_serial_ports(void) | |||
365 | /* Check for known pciclass, and also check wether we have | 365 | /* Check for known pciclass, and also check wether we have |
366 | * a device with child nodes for ports or not | 366 | * a device with child nodes for ports or not |
367 | */ | 367 | */ |
368 | if (device_is_compatible(np, "pciclass,0700") || | 368 | if (of_device_is_compatible(np, "pciclass,0700") || |
369 | device_is_compatible(np, "pciclass,070002")) | 369 | of_device_is_compatible(np, "pciclass,070002")) |
370 | pci = np; | 370 | pci = np; |
371 | else if (device_is_compatible(parent, "pciclass,0700") || | 371 | else if (of_device_is_compatible(parent, "pciclass,0700") || |
372 | device_is_compatible(parent, "pciclass,070002")) | 372 | of_device_is_compatible(parent, "pciclass,070002")) |
373 | pci = parent; | 373 | pci = parent; |
374 | else { | 374 | else { |
375 | of_node_put(parent); | 375 | of_node_put(parent); |
diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c new file mode 100644 index 000000000000..c62d1012c013 --- /dev/null +++ b/arch/powerpc/kernel/msi.c | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * Copyright 2006-2007, Michael Ellerman, IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/msi.h> | ||
12 | |||
13 | #include <asm/machdep.h> | ||
14 | |||
15 | int arch_msi_check_device(struct pci_dev* dev, int nvec, int type) | ||
16 | { | ||
17 | if (!ppc_md.setup_msi_irqs || !ppc_md.teardown_msi_irqs) { | ||
18 | pr_debug("msi: Platform doesn't provide MSI callbacks.\n"); | ||
19 | return -ENOSYS; | ||
20 | } | ||
21 | |||
22 | if (ppc_md.msi_check_device) { | ||
23 | pr_debug("msi: Using platform check routine.\n"); | ||
24 | return ppc_md.msi_check_device(dev, nvec, type); | ||
25 | } | ||
26 | |||
27 | return 0; | ||
28 | } | ||
29 | |||
30 | int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | ||
31 | { | ||
32 | return ppc_md.setup_msi_irqs(dev, nvec, type); | ||
33 | } | ||
34 | |||
35 | void arch_teardown_msi_irqs(struct pci_dev *dev) | ||
36 | { | ||
37 | return ppc_md.teardown_msi_irqs(dev); | ||
38 | } | ||
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 0c8ea7659d92..a464d67248df 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, | |||
27 | match &= node->type | 27 | match &= node->type |
28 | && !strcmp(matches->type, node->type); | 28 | && !strcmp(matches->type, node->type); |
29 | if (matches->compatible[0]) | 29 | if (matches->compatible[0]) |
30 | match &= device_is_compatible(node, | 30 | match &= of_device_is_compatible(node, |
31 | matches->compatible); | 31 | matches->compatible); |
32 | if (match) | 32 | if (match) |
33 | return matches; | 33 | return matches; |
@@ -120,8 +120,8 @@ void of_device_unregister(struct of_device *ofdev) | |||
120 | } | 120 | } |
121 | 121 | ||
122 | 122 | ||
123 | static ssize_t of_device_get_modalias(struct of_device *ofdev, | 123 | ssize_t of_device_get_modalias(struct of_device *ofdev, |
124 | char *str, ssize_t len) | 124 | char *str, ssize_t len) |
125 | { | 125 | { |
126 | const char *compat; | 126 | const char *compat; |
127 | int cplen, i; | 127 | int cplen, i; |
@@ -239,3 +239,4 @@ EXPORT_SYMBOL(of_dev_get); | |||
239 | EXPORT_SYMBOL(of_dev_put); | 239 | EXPORT_SYMBOL(of_dev_put); |
240 | EXPORT_SYMBOL(of_release_dev); | 240 | EXPORT_SYMBOL(of_release_dev); |
241 | EXPORT_SYMBOL(of_device_uevent); | 241 | EXPORT_SYMBOL(of_device_uevent); |
242 | EXPORT_SYMBOL(of_device_get_modalias); | ||
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 908ed7926db4..84c34d979a88 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <asm/ppc-pci.h> | 29 | #include <asm/ppc-pci.h> |
30 | #include <asm/atomic.h> | 30 | #include <asm/atomic.h> |
31 | 31 | ||
32 | |||
33 | /* | 32 | /* |
34 | * The list of OF IDs below is used for matching bus types in the | 33 | * The list of OF IDs below is used for matching bus types in the |
35 | * system whose devices are to be exposed as of_platform_devices. | 34 | * system whose devices are to be exposed as of_platform_devices. |
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index f022862de344..e66064b5093a 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, | |||
1658 | int i; | 1658 | int i; |
1659 | 1659 | ||
1660 | if (page_is_ram(pfn)) | 1660 | if (page_is_ram(pfn)) |
1661 | return prot; | 1661 | return __pgprot(prot); |
1662 | 1662 | ||
1663 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | 1663 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; |
1664 | 1664 | ||
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 7138092826aa..6d05a1f377b5 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, | |||
1006 | 1006 | ||
1007 | switch ((pci_space >> 24) & 0x3) { | 1007 | switch ((pci_space >> 24) & 0x3) { |
1008 | case 1: /* I/O space */ | 1008 | case 1: /* I/O space */ |
1009 | hose->io_base_phys = cpu_phys_addr; | 1009 | hose->io_base_phys = cpu_phys_addr - pci_addr; |
1010 | hose->pci_io_size = size; | 1010 | /* handle from 0 to top of I/O window */ |
1011 | hose->pci_io_size = pci_addr + size; | ||
1011 | 1012 | ||
1012 | res = &hose->io_resource; | 1013 | res = &hose->io_resource; |
1013 | res->flags = IORESOURCE_IO; | 1014 | res->flags = IORESOURCE_IO; |
@@ -1117,8 +1118,8 @@ static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys, | |||
1117 | } else { | 1118 | } else { |
1118 | /* Root Bus */ | 1119 | /* Root Bus */ |
1119 | res = &hose->io_resource; | 1120 | res = &hose->io_resource; |
1120 | *start_phys = hose->io_base_phys; | 1121 | *start_phys = hose->io_base_phys + res->start; |
1121 | *start_virt = (unsigned long) hose->io_base_virt; | 1122 | *start_virt = (unsigned long) hose->io_base_virt + res->start; |
1122 | if (res->end > res->start) | 1123 | if (res->end > res->start) |
1123 | *size = res->end - res->start + 1; | 1124 | *size = res->end - res->start + 1; |
1124 | else { | 1125 | else { |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index ff252aaead12..c96fa9bd35a4 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -66,7 +66,6 @@ EXPORT_SYMBOL(clear_pages); | |||
66 | EXPORT_SYMBOL(ISA_DMA_THRESHOLD); | 66 | EXPORT_SYMBOL(ISA_DMA_THRESHOLD); |
67 | EXPORT_SYMBOL(DMA_MODE_READ); | 67 | EXPORT_SYMBOL(DMA_MODE_READ); |
68 | EXPORT_SYMBOL(DMA_MODE_WRITE); | 68 | EXPORT_SYMBOL(DMA_MODE_WRITE); |
69 | EXPORT_SYMBOL(__div64_32); | ||
70 | 69 | ||
71 | EXPORT_SYMBOL(do_signal); | 70 | EXPORT_SYMBOL(do_signal); |
72 | EXPORT_SYMBOL(transfer_to_handler); | 71 | EXPORT_SYMBOL(transfer_to_handler); |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index e27d9d1b6e67..d6047c441034 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) | |||
635 | /* ibm,dynamic-reconfiguration-memory property supported */ | 635 | /* ibm,dynamic-reconfiguration-memory property supported */ |
636 | #define OV5_DRCONF_MEMORY 0x20 | 636 | #define OV5_DRCONF_MEMORY 0x20 |
637 | #define OV5_LARGE_PAGES 0x10 /* large pages supported */ | 637 | #define OV5_LARGE_PAGES 0x10 /* large pages supported */ |
638 | /* PCIe/MSI support. Without MSI full PCIe is not supported */ | ||
639 | #ifdef CONFIG_PCI_MSI | ||
640 | #define OV5_MSI 0x01 /* PCIe/MSI support */ | ||
641 | #else | ||
642 | #define OV5_MSI 0x00 | ||
643 | #endif /* CONFIG_PCI_MSI */ | ||
638 | 644 | ||
639 | /* | 645 | /* |
640 | * The architecture vector has an array of PVR mask/value pairs, | 646 | * The architecture vector has an array of PVR mask/value pairs, |
@@ -679,7 +685,7 @@ static unsigned char ibm_architecture_vec[] = { | |||
679 | /* option vector 5: PAPR/OF options */ | 685 | /* option vector 5: PAPR/OF options */ |
680 | 3 - 2, /* length */ | 686 | 3 - 2, /* length */ |
681 | 0, /* don't ignore, don't halt */ | 687 | 0, /* don't ignore, don't halt */ |
682 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY, | 688 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI, |
683 | }; | 689 | }; |
684 | 690 | ||
685 | /* Old method - ELF header with PT_NOTE sections */ | 691 | /* Old method - ELF header with PT_NOTE sections */ |
@@ -967,7 +973,7 @@ static unsigned long __init prom_next_cell(int s, cell_t **cellp) | |||
967 | * If problems seem to show up, it would be a good start to track | 973 | * If problems seem to show up, it would be a good start to track |
968 | * them down. | 974 | * them down. |
969 | */ | 975 | */ |
970 | static void reserve_mem(u64 base, u64 size) | 976 | static void __init reserve_mem(u64 base, u64 size) |
971 | { | 977 | { |
972 | u64 top = base + size; | 978 | u64 top = base + size; |
973 | unsigned long cnt = RELOC(mem_reserve_cnt); | 979 | unsigned long cnt = RELOC(mem_reserve_cnt); |
@@ -2153,7 +2159,7 @@ static void __init fixup_device_tree_efika(void) | |||
2153 | 3,12,0, 3,13,0, 3,14,0, 3,15,0 }; | 2159 | 3,12,0, 3,13,0, 3,14,0, 3,15,0 }; |
2154 | struct subst_entry efika_subst_table[] = { | 2160 | struct subst_entry efika_subst_table[] = { |
2155 | { "/", "device_type", prop_cstr("efika") }, | 2161 | { "/", "device_type", prop_cstr("efika") }, |
2156 | { "/builtin", "compatible", prop_cstr("soc") }, | 2162 | { "/builtin", "device_type", prop_cstr("soc") }, |
2157 | { "/builtin/ata", "compatible", prop_cstr("mpc5200b-ata\0mpc5200-ata"), }, | 2163 | { "/builtin/ata", "compatible", prop_cstr("mpc5200b-ata\0mpc5200-ata"), }, |
2158 | { "/builtin/bestcomm", "compatible", prop_cstr("mpc5200b-bestcomm\0mpc5200-bestcomm") }, | 2164 | { "/builtin/bestcomm", "compatible", prop_cstr("mpc5200b-bestcomm\0mpc5200-bestcomm") }, |
2159 | { "/builtin/bestcomm", "interrupts", prop_bcomm_irq, sizeof(prop_bcomm_irq) }, | 2165 | { "/builtin/bestcomm", "interrupts", prop_bcomm_irq, sizeof(prop_bcomm_irq) }, |
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index aa40a5307294..b5c96af955c6 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c | |||
@@ -1042,3 +1042,28 @@ const void *of_get_mac_address(struct device_node *np) | |||
1042 | } | 1042 | } |
1043 | EXPORT_SYMBOL(of_get_mac_address); | 1043 | EXPORT_SYMBOL(of_get_mac_address); |
1044 | 1044 | ||
1045 | int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) | ||
1046 | { | ||
1047 | int irq = irq_of_parse_and_map(dev, index); | ||
1048 | |||
1049 | /* Only dereference the resource if both the | ||
1050 | * resource and the irq are valid. */ | ||
1051 | if (r && irq != NO_IRQ) { | ||
1052 | r->start = r->end = irq; | ||
1053 | r->flags = IORESOURCE_IRQ; | ||
1054 | } | ||
1055 | |||
1056 | return irq; | ||
1057 | } | ||
1058 | EXPORT_SYMBOL_GPL(of_irq_to_resource); | ||
1059 | |||
1060 | void __iomem *of_iomap(struct device_node *np, int index) | ||
1061 | { | ||
1062 | struct resource res; | ||
1063 | |||
1064 | if (of_address_to_resource(np, index, &res)) | ||
1065 | return NULL; | ||
1066 | |||
1067 | return ioremap(res.start, 1 + res.end - res.start); | ||
1068 | } | ||
1069 | EXPORT_SYMBOL(of_iomap); | ||
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index d8e503b2e1af..22f1ef1b3100 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -176,10 +176,10 @@ static struct call_data_struct { | |||
176 | #define SMP_CALL_TIMEOUT 8 | 176 | #define SMP_CALL_TIMEOUT 8 |
177 | 177 | ||
178 | /* | 178 | /* |
179 | * This function sends a 'generic call function' IPI to all other CPUs | 179 | * These functions send a 'generic call function' IPI to other online |
180 | * in the system. | 180 | * CPUS in the system. |
181 | * | 181 | * |
182 | * [SUMMARY] Run a function on all other CPUs. | 182 | * [SUMMARY] Run a function on other CPUs. |
183 | * <func> The function to run. This must be fast and non-blocking. | 183 | * <func> The function to run. This must be fast and non-blocking. |
184 | * <info> An arbitrary pointer to pass to the function. | 184 | * <info> An arbitrary pointer to pass to the function. |
185 | * <nonatomic> currently unused. | 185 | * <nonatomic> currently unused. |
@@ -190,18 +190,26 @@ static struct call_data_struct { | |||
190 | * You must not call this function with disabled interrupts or from a | 190 | * You must not call this function with disabled interrupts or from a |
191 | * hardware interrupt handler or from a bottom half handler. | 191 | * hardware interrupt handler or from a bottom half handler. |
192 | */ | 192 | */ |
193 | int smp_call_function (void (*func) (void *info), void *info, int nonatomic, | 193 | int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, |
194 | int wait) | 194 | int wait, cpumask_t map) |
195 | { | 195 | { |
196 | struct call_data_struct data; | 196 | struct call_data_struct data; |
197 | int ret = -1, cpus; | 197 | int ret = -1, num_cpus; |
198 | int cpu; | ||
198 | u64 timeout; | 199 | u64 timeout; |
199 | 200 | ||
200 | /* Can deadlock when called with interrupts disabled */ | 201 | /* Can deadlock when called with interrupts disabled */ |
201 | WARN_ON(irqs_disabled()); | 202 | WARN_ON(irqs_disabled()); |
202 | 203 | ||
204 | /* remove 'self' from the map */ | ||
205 | if (cpu_isset(smp_processor_id(), map)) | ||
206 | cpu_clear(smp_processor_id(), map); | ||
207 | |||
208 | /* sanity check the map, remove any non-online processors. */ | ||
209 | cpus_and(map, map, cpu_online_map); | ||
210 | |||
203 | if (unlikely(smp_ops == NULL)) | 211 | if (unlikely(smp_ops == NULL)) |
204 | return -1; | 212 | return ret; |
205 | 213 | ||
206 | data.func = func; | 214 | data.func = func; |
207 | data.info = info; | 215 | data.info = info; |
@@ -213,40 +221,42 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, | |||
213 | spin_lock(&call_lock); | 221 | spin_lock(&call_lock); |
214 | /* Must grab online cpu count with preempt disabled, otherwise | 222 | /* Must grab online cpu count with preempt disabled, otherwise |
215 | * it can change. */ | 223 | * it can change. */ |
216 | cpus = num_online_cpus() - 1; | 224 | num_cpus = num_online_cpus() - 1; |
217 | if (!cpus) { | 225 | if (!num_cpus || cpus_empty(map)) { |
218 | ret = 0; | 226 | ret = 0; |
219 | goto out; | 227 | goto out; |
220 | } | 228 | } |
221 | 229 | ||
222 | call_data = &data; | 230 | call_data = &data; |
223 | smp_wmb(); | 231 | smp_wmb(); |
224 | /* Send a message to all other CPUs and wait for them to respond */ | 232 | /* Send a message to all CPUs in the map */ |
225 | smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION); | 233 | for_each_cpu_mask(cpu, map) |
234 | smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNCTION); | ||
226 | 235 | ||
227 | timeout = get_tb() + (u64) SMP_CALL_TIMEOUT * tb_ticks_per_sec; | 236 | timeout = get_tb() + (u64) SMP_CALL_TIMEOUT * tb_ticks_per_sec; |
228 | 237 | ||
229 | /* Wait for response */ | 238 | /* Wait for indication that they have received the message */ |
230 | while (atomic_read(&data.started) != cpus) { | 239 | while (atomic_read(&data.started) != num_cpus) { |
231 | HMT_low(); | 240 | HMT_low(); |
232 | if (get_tb() >= timeout) { | 241 | if (get_tb() >= timeout) { |
233 | printk("smp_call_function on cpu %d: other cpus not " | 242 | printk("smp_call_function on cpu %d: other cpus not " |
234 | "responding (%d)\n", smp_processor_id(), | 243 | "responding (%d)\n", smp_processor_id(), |
235 | atomic_read(&data.started)); | 244 | atomic_read(&data.started)); |
236 | debugger(NULL); | 245 | debugger(NULL); |
237 | goto out; | 246 | goto out; |
238 | } | 247 | } |
239 | } | 248 | } |
240 | 249 | ||
250 | /* optionally wait for the CPUs to complete */ | ||
241 | if (wait) { | 251 | if (wait) { |
242 | while (atomic_read(&data.finished) != cpus) { | 252 | while (atomic_read(&data.finished) != num_cpus) { |
243 | HMT_low(); | 253 | HMT_low(); |
244 | if (get_tb() >= timeout) { | 254 | if (get_tb() >= timeout) { |
245 | printk("smp_call_function on cpu %d: other " | 255 | printk("smp_call_function on cpu %d: other " |
246 | "cpus not finishing (%d/%d)\n", | 256 | "cpus not finishing (%d/%d)\n", |
247 | smp_processor_id(), | 257 | smp_processor_id(), |
248 | atomic_read(&data.finished), | 258 | atomic_read(&data.finished), |
249 | atomic_read(&data.started)); | 259 | atomic_read(&data.started)); |
250 | debugger(NULL); | 260 | debugger(NULL); |
251 | goto out; | 261 | goto out; |
252 | } | 262 | } |
@@ -262,8 +272,29 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, | |||
262 | return ret; | 272 | return ret; |
263 | } | 273 | } |
264 | 274 | ||
275 | int smp_call_function(void (*func) (void *info), void *info, int nonatomic, | ||
276 | int wait) | ||
277 | { | ||
278 | return smp_call_function_map(func,info,nonatomic,wait,cpu_online_map); | ||
279 | } | ||
265 | EXPORT_SYMBOL(smp_call_function); | 280 | EXPORT_SYMBOL(smp_call_function); |
266 | 281 | ||
282 | int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int nonatomic, | ||
283 | int wait) | ||
284 | { | ||
285 | cpumask_t map=CPU_MASK_NONE; | ||
286 | |||
287 | if (!cpu_online(cpu)) | ||
288 | return -EINVAL; | ||
289 | |||
290 | if (cpu == smp_processor_id()) | ||
291 | return -EBUSY; | ||
292 | |||
293 | cpu_set(cpu, map); | ||
294 | return smp_call_function_map(func,info,nonatomic,wait,map); | ||
295 | } | ||
296 | EXPORT_SYMBOL(smp_call_function_single); | ||
297 | |||
267 | void smp_call_function_interrupt(void) | 298 | void smp_call_function_interrupt(void) |
268 | { | 299 | { |
269 | void (*func) (void *info); | 300 | void (*func) (void *info); |
diff --git a/arch/powerpc/kernel/swsusp.c b/arch/powerpc/kernel/swsusp.c new file mode 100644 index 000000000000..064a7ba4f02c --- /dev/null +++ b/arch/powerpc/kernel/swsusp.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Common powerpc suspend code for 32 and 64 bits | ||
3 | * | ||
4 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/sched.h> | ||
13 | #include <asm/suspend.h> | ||
14 | #include <asm/system.h> | ||
15 | #include <asm/current.h> | ||
16 | #include <asm/mmu_context.h> | ||
17 | |||
18 | void save_processor_state(void) | ||
19 | { | ||
20 | /* | ||
21 | * flush out all the special registers so we don't need | ||
22 | * to save them in the snapshot | ||
23 | */ | ||
24 | flush_fp_to_thread(current); | ||
25 | flush_altivec_to_thread(current); | ||
26 | flush_spe_to_thread(current); | ||
27 | |||
28 | #ifdef CONFIG_PPC64 | ||
29 | hard_irq_disable(); | ||
30 | #endif | ||
31 | |||
32 | } | ||
33 | |||
34 | void restore_processor_state(void) | ||
35 | { | ||
36 | #ifdef CONFIG_PPC32 | ||
37 | set_context(current->active_mm->context.id, current->active_mm->pgd); | ||
38 | #endif | ||
39 | |||
40 | #ifdef CONFIG_PPC64 | ||
41 | hard_irq_enable(); | ||
42 | #endif | ||
43 | } | ||
diff --git a/arch/powerpc/kernel/swsusp_64.c b/arch/powerpc/kernel/swsusp_64.c new file mode 100644 index 000000000000..6f3f0697274e --- /dev/null +++ b/arch/powerpc/kernel/swsusp_64.c | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * PowerPC 64-bit swsusp implementation | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPLv2 | ||
7 | */ | ||
8 | |||
9 | #include <asm/system.h> | ||
10 | #include <asm/iommu.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | |||
14 | void do_after_copyback(void) | ||
15 | { | ||
16 | iommu_restore(); | ||
17 | touch_softlockup_watchdog(); | ||
18 | mb(); | ||
19 | } | ||
20 | |||
21 | void _iommu_save(void) | ||
22 | { | ||
23 | iommu_save(); | ||
24 | } | ||
diff --git a/arch/powerpc/kernel/swsusp_asm64.S b/arch/powerpc/kernel/swsusp_asm64.S new file mode 100644 index 000000000000..e092c3cbdb9b --- /dev/null +++ b/arch/powerpc/kernel/swsusp_asm64.S | |||
@@ -0,0 +1,228 @@ | |||
1 | /* | ||
2 | * PowerPC 64-bit swsusp implementation | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPLv2 | ||
7 | */ | ||
8 | |||
9 | #include <linux/threads.h> | ||
10 | #include <asm/processor.h> | ||
11 | #include <asm/page.h> | ||
12 | #include <asm/cputable.h> | ||
13 | #include <asm/thread_info.h> | ||
14 | #include <asm/ppc_asm.h> | ||
15 | #include <asm/asm-offsets.h> | ||
16 | |||
17 | /* | ||
18 | * Structure for storing CPU registers on the save area. | ||
19 | */ | ||
20 | #define SL_r1 0x00 /* stack pointer */ | ||
21 | #define SL_PC 0x08 | ||
22 | #define SL_MSR 0x10 | ||
23 | #define SL_SDR1 0x18 | ||
24 | #define SL_XER 0x20 | ||
25 | #define SL_TB 0x40 | ||
26 | #define SL_r2 0x48 | ||
27 | #define SL_CR 0x50 | ||
28 | #define SL_LR 0x58 | ||
29 | #define SL_r12 0x60 | ||
30 | #define SL_r13 0x68 | ||
31 | #define SL_r14 0x70 | ||
32 | #define SL_r15 0x78 | ||
33 | #define SL_r16 0x80 | ||
34 | #define SL_r17 0x88 | ||
35 | #define SL_r18 0x90 | ||
36 | #define SL_r19 0x98 | ||
37 | #define SL_r20 0xa0 | ||
38 | #define SL_r21 0xa8 | ||
39 | #define SL_r22 0xb0 | ||
40 | #define SL_r23 0xb8 | ||
41 | #define SL_r24 0xc0 | ||
42 | #define SL_r25 0xc8 | ||
43 | #define SL_r26 0xd0 | ||
44 | #define SL_r27 0xd8 | ||
45 | #define SL_r28 0xe0 | ||
46 | #define SL_r29 0xe8 | ||
47 | #define SL_r30 0xf0 | ||
48 | #define SL_r31 0xf8 | ||
49 | #define SL_SIZE SL_r31+8 | ||
50 | |||
51 | /* these macros rely on the save area being | ||
52 | * pointed to by r11 */ | ||
53 | #define SAVE_SPECIAL(special) \ | ||
54 | mf##special r0 ;\ | ||
55 | std r0, SL_##special(r11) | ||
56 | #define RESTORE_SPECIAL(special) \ | ||
57 | ld r0, SL_##special(r11) ;\ | ||
58 | mt##special r0 | ||
59 | #define SAVE_REGISTER(reg) \ | ||
60 | std reg, SL_##reg(r11) | ||
61 | #define RESTORE_REGISTER(reg) \ | ||
62 | ld reg, SL_##reg(r11) | ||
63 | |||
64 | /* space for storing cpu state */ | ||
65 | .section .data | ||
66 | .align 5 | ||
67 | swsusp_save_area: | ||
68 | .space SL_SIZE | ||
69 | |||
70 | .section ".toc","aw" | ||
71 | swsusp_save_area_ptr: | ||
72 | .tc swsusp_save_area[TC],swsusp_save_area | ||
73 | restore_pblist_ptr: | ||
74 | .tc restore_pblist[TC],restore_pblist | ||
75 | |||
76 | .section .text | ||
77 | .align 5 | ||
78 | _GLOBAL(swsusp_arch_suspend) | ||
79 | ld r11,swsusp_save_area_ptr@toc(r2) | ||
80 | SAVE_SPECIAL(LR) | ||
81 | SAVE_REGISTER(r1) | ||
82 | SAVE_SPECIAL(CR) | ||
83 | SAVE_SPECIAL(TB) | ||
84 | SAVE_REGISTER(r2) | ||
85 | SAVE_REGISTER(r12) | ||
86 | SAVE_REGISTER(r13) | ||
87 | SAVE_REGISTER(r14) | ||
88 | SAVE_REGISTER(r15) | ||
89 | SAVE_REGISTER(r16) | ||
90 | SAVE_REGISTER(r17) | ||
91 | SAVE_REGISTER(r18) | ||
92 | SAVE_REGISTER(r19) | ||
93 | SAVE_REGISTER(r20) | ||
94 | SAVE_REGISTER(r21) | ||
95 | SAVE_REGISTER(r22) | ||
96 | SAVE_REGISTER(r23) | ||
97 | SAVE_REGISTER(r24) | ||
98 | SAVE_REGISTER(r25) | ||
99 | SAVE_REGISTER(r26) | ||
100 | SAVE_REGISTER(r27) | ||
101 | SAVE_REGISTER(r28) | ||
102 | SAVE_REGISTER(r29) | ||
103 | SAVE_REGISTER(r30) | ||
104 | SAVE_REGISTER(r31) | ||
105 | SAVE_SPECIAL(MSR) | ||
106 | SAVE_SPECIAL(SDR1) | ||
107 | SAVE_SPECIAL(XER) | ||
108 | |||
109 | /* we push the stack up 128 bytes but don't store the | ||
110 | * stack pointer on the stack like a real stackframe */ | ||
111 | addi r1,r1,-128 | ||
112 | |||
113 | bl _iommu_save | ||
114 | bl swsusp_save | ||
115 | |||
116 | /* restore LR */ | ||
117 | ld r11,swsusp_save_area_ptr@toc(r2) | ||
118 | RESTORE_SPECIAL(LR) | ||
119 | addi r1,r1,128 | ||
120 | |||
121 | blr | ||
122 | |||
123 | /* Resume code */ | ||
124 | _GLOBAL(swsusp_arch_resume) | ||
125 | /* Stop pending alitvec streams and memory accesses */ | ||
126 | BEGIN_FTR_SECTION | ||
127 | DSSALL | ||
128 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
129 | sync | ||
130 | |||
131 | ld r12,restore_pblist_ptr@toc(r2) | ||
132 | ld r12,0(r12) | ||
133 | |||
134 | cmpdi r12,0 | ||
135 | beq- nothing_to_copy | ||
136 | li r15,512 | ||
137 | copyloop: | ||
138 | ld r13,pbe_address(r12) | ||
139 | ld r14,pbe_orig_address(r12) | ||
140 | |||
141 | mtctr r15 | ||
142 | li r10,0 | ||
143 | copy_page_loop: | ||
144 | ldx r0,r10,r13 | ||
145 | stdx r0,r10,r14 | ||
146 | addi r10,r10,8 | ||
147 | bdnz copy_page_loop | ||
148 | |||
149 | ld r12,pbe_next(r12) | ||
150 | cmpdi r12,0 | ||
151 | bne+ copyloop | ||
152 | nothing_to_copy: | ||
153 | |||
154 | /* flush caches */ | ||
155 | lis r3, 0x10 | ||
156 | mtctr r3 | ||
157 | li r3, 0 | ||
158 | ori r3, r3, CONFIG_KERNEL_START>>48 | ||
159 | li r0, 48 | ||
160 | sld r3, r3, r0 | ||
161 | li r0, 0 | ||
162 | 1: | ||
163 | dcbf r0,r3 | ||
164 | addi r3,r3,0x20 | ||
165 | bdnz 1b | ||
166 | |||
167 | sync | ||
168 | |||
169 | tlbia | ||
170 | |||
171 | ld r11,swsusp_save_area_ptr@toc(r2) | ||
172 | |||
173 | RESTORE_SPECIAL(CR) | ||
174 | |||
175 | /* restore timebase */ | ||
176 | /* load saved tb */ | ||
177 | ld r1, SL_TB(r11) | ||
178 | /* get upper 32 bits of it */ | ||
179 | srdi r2, r1, 32 | ||
180 | /* clear tb lower to avoid wrap */ | ||
181 | li r0, 0 | ||
182 | mttbl r0 | ||
183 | /* set tb upper */ | ||
184 | mttbu r2 | ||
185 | /* set tb lower */ | ||
186 | mttbl r1 | ||
187 | |||
188 | /* restore registers */ | ||
189 | RESTORE_REGISTER(r1) | ||
190 | RESTORE_REGISTER(r2) | ||
191 | RESTORE_REGISTER(r12) | ||
192 | RESTORE_REGISTER(r13) | ||
193 | RESTORE_REGISTER(r14) | ||
194 | RESTORE_REGISTER(r15) | ||
195 | RESTORE_REGISTER(r16) | ||
196 | RESTORE_REGISTER(r17) | ||
197 | RESTORE_REGISTER(r18) | ||
198 | RESTORE_REGISTER(r19) | ||
199 | RESTORE_REGISTER(r20) | ||
200 | RESTORE_REGISTER(r21) | ||
201 | RESTORE_REGISTER(r22) | ||
202 | RESTORE_REGISTER(r23) | ||
203 | RESTORE_REGISTER(r24) | ||
204 | RESTORE_REGISTER(r25) | ||
205 | RESTORE_REGISTER(r26) | ||
206 | RESTORE_REGISTER(r27) | ||
207 | RESTORE_REGISTER(r28) | ||
208 | RESTORE_REGISTER(r29) | ||
209 | RESTORE_REGISTER(r30) | ||
210 | RESTORE_REGISTER(r31) | ||
211 | /* can't use RESTORE_SPECIAL(MSR) */ | ||
212 | ld r0, SL_MSR(r11) | ||
213 | mtmsrd r0, 0 | ||
214 | RESTORE_SPECIAL(SDR1) | ||
215 | RESTORE_SPECIAL(XER) | ||
216 | |||
217 | sync | ||
218 | |||
219 | addi r1,r1,-128 | ||
220 | bl slb_flush_and_rebolt | ||
221 | bl do_after_copyback | ||
222 | addi r1,r1,128 | ||
223 | |||
224 | ld r11,swsusp_save_area_ptr@toc(r2) | ||
225 | RESTORE_SPECIAL(LR) | ||
226 | |||
227 | li r3, 0 | ||
228 | blr | ||
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 933e214c33e8..cae39d9dfe48 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -499,4 +499,4 @@ static int __init topology_init(void) | |||
499 | 499 | ||
500 | return 0; | 500 | return 0; |
501 | } | 501 | } |
502 | __initcall(topology_init); | 502 | subsys_initcall(topology_init); |
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 147a2d83de10..87703df87509 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c | |||
@@ -51,6 +51,9 @@ void __init udbg_early_init(void) | |||
51 | udbg_init_pas_realmode(); | 51 | udbg_init_pas_realmode(); |
52 | #elif defined(CONFIG_BOOTX_TEXT) | 52 | #elif defined(CONFIG_BOOTX_TEXT) |
53 | udbg_init_btext(); | 53 | udbg_init_btext(); |
54 | #elif defined(CONFIG_PPC_EARLY_DEBUG_44x) | ||
55 | /* PPC44x debug */ | ||
56 | udbg_init_44x_as1(); | ||
54 | #endif | 57 | #endif |
55 | } | 58 | } |
56 | 59 | ||
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index a963f657222b..7afab5bcd61a 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) | |||
191 | udbg_getc_poll = NULL; | 191 | udbg_getc_poll = NULL; |
192 | } | 192 | } |
193 | #endif /* CONFIG_PPC_MAPLE */ | 193 | #endif /* CONFIG_PPC_MAPLE */ |
194 | |||
195 | #ifdef CONFIG_PPC_EARLY_DEBUG_44x | ||
196 | #include <platforms/44x/44x.h> | ||
197 | |||
198 | static void udbg_44x_as1_putc(char c) | ||
199 | { | ||
200 | if (udbg_comport) { | ||
201 | while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0) | ||
202 | /* wait for idle */; | ||
203 | as1_writeb(c, &udbg_comport->thr); eieio(); | ||
204 | if (c == '\n') | ||
205 | udbg_44x_as1_putc('\r'); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | void __init udbg_init_44x_as1(void) | ||
210 | { | ||
211 | udbg_comport = | ||
212 | (volatile struct NS16550 __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR; | ||
213 | |||
214 | udbg_putc = udbg_44x_as1_putc; | ||
215 | } | ||
216 | #endif /* CONFIG_PPC_EARLY_DEBUG_44x */ | ||
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index b2c1b67a10a7..62c1bc12ea39 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( | |||
117 | { | 117 | { |
118 | while (ids->type[0] != '\0') { | 118 | while (ids->type[0] != '\0') { |
119 | if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) && | 119 | if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) && |
120 | device_is_compatible(dev->dev.archdata.of_node, | 120 | of_device_is_compatible(dev->dev.archdata.of_node, |
121 | ids->compat)) | 121 | ids->compat)) |
122 | return ids; | 122 | return ids; |
123 | ids++; | 123 | ids++; |