diff options
Diffstat (limited to 'arch/powerpc')
81 files changed, 1609 insertions, 958 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 4bb2e9310a56..20f45a8b87e3 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -626,20 +626,6 @@ config ADVANCED_OPTIONS | |||
| 626 | comment "Default settings for advanced configuration options are used" | 626 | comment "Default settings for advanced configuration options are used" |
| 627 | depends on !ADVANCED_OPTIONS | 627 | depends on !ADVANCED_OPTIONS |
| 628 | 628 | ||
| 629 | config HIGHMEM_START_BOOL | ||
| 630 | bool "Set high memory pool address" | ||
| 631 | depends on ADVANCED_OPTIONS && HIGHMEM | ||
| 632 | help | ||
| 633 | This option allows you to set the base address of the kernel virtual | ||
| 634 | area used to map high memory pages. This can be useful in | ||
| 635 | optimizing the layout of kernel virtual memory. | ||
| 636 | |||
| 637 | Say N here unless you know what you are doing. | ||
| 638 | |||
| 639 | config HIGHMEM_START | ||
| 640 | hex "Virtual start address of high memory pool" if HIGHMEM_START_BOOL | ||
| 641 | default "0xfe000000" | ||
| 642 | |||
| 643 | config LOWMEM_SIZE_BOOL | 629 | config LOWMEM_SIZE_BOOL |
| 644 | bool "Set maximum low memory" | 630 | bool "Set maximum low memory" |
| 645 | depends on ADVANCED_OPTIONS | 631 | depends on ADVANCED_OPTIONS |
| @@ -656,21 +642,76 @@ config LOWMEM_SIZE | |||
| 656 | hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL | 642 | hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL |
| 657 | default "0x30000000" | 643 | default "0x30000000" |
| 658 | 644 | ||
| 645 | config RELOCATABLE | ||
| 646 | bool "Build a relocatable kernel (EXPERIMENTAL)" | ||
| 647 | depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE | ||
| 648 | help | ||
| 649 | This builds a kernel image that is capable of running at the | ||
| 650 | location the kernel is loaded at (some alignment restrictions may | ||
| 651 | exist). | ||
| 652 | |||
| 653 | One use is for the kexec on panic case where the recovery kernel | ||
| 654 | must live at a different physical address than the primary | ||
| 655 | kernel. | ||
| 656 | |||
| 657 | Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address | ||
| 658 | it has been loaded at and the compile time physical addresses | ||
| 659 | CONFIG_PHYSICAL_START is ignored. However CONFIG_PHYSICAL_START | ||
| 660 | setting can still be useful to bootwrappers that need to know the | ||
| 661 | load location of the kernel (eg. u-boot/mkimage). | ||
| 662 | |||
| 663 | config PAGE_OFFSET_BOOL | ||
| 664 | bool "Set custom page offset address" | ||
| 665 | depends on ADVANCED_OPTIONS | ||
| 666 | help | ||
| 667 | This option allows you to set the kernel virtual address at which | ||
| 668 | the kernel will map low memory. This can be useful in optimizing | ||
| 669 | the virtual memory layout of the system. | ||
| 670 | |||
| 671 | Say N here unless you know what you are doing. | ||
| 672 | |||
| 673 | config PAGE_OFFSET | ||
| 674 | hex "Virtual address of memory base" if PAGE_OFFSET_BOOL | ||
| 675 | default "0xc0000000" | ||
| 676 | |||
| 659 | config KERNEL_START_BOOL | 677 | config KERNEL_START_BOOL |
| 660 | bool "Set custom kernel base address" | 678 | bool "Set custom kernel base address" |
| 661 | depends on ADVANCED_OPTIONS | 679 | depends on ADVANCED_OPTIONS |
| 662 | help | 680 | help |
| 663 | This option allows you to set the kernel virtual address at which | 681 | This option allows you to set the kernel virtual address at which |
| 664 | the kernel will map low memory (the kernel image will be linked at | 682 | the kernel will be loaded. Normally this should match PAGE_OFFSET |
| 665 | this address). This can be useful in optimizing the virtual memory | 683 | however there are times (like kdump) that one might not want them |
| 666 | layout of the system. | 684 | to be the same. |
| 667 | 685 | ||
| 668 | Say N here unless you know what you are doing. | 686 | Say N here unless you know what you are doing. |
| 669 | 687 | ||
| 670 | config KERNEL_START | 688 | config KERNEL_START |
| 671 | hex "Virtual address of kernel base" if KERNEL_START_BOOL | 689 | hex "Virtual address of kernel base" if KERNEL_START_BOOL |
| 690 | default PAGE_OFFSET if PAGE_OFFSET_BOOL | ||
| 691 | default "0xc2000000" if CRASH_DUMP | ||
| 672 | default "0xc0000000" | 692 | default "0xc0000000" |
| 673 | 693 | ||
| 694 | config PHYSICAL_START_BOOL | ||
| 695 | bool "Set physical address where the kernel is loaded" | ||
| 696 | depends on ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE | ||
| 697 | help | ||
| 698 | This gives the physical address where the kernel is loaded. | ||
| 699 | |||
| 700 | Say N here unless you know what you are doing. | ||
| 701 | |||
| 702 | config PHYSICAL_START | ||
| 703 | hex "Physical address where the kernel is loaded" if PHYSICAL_START_BOOL | ||
| 704 | default "0x02000000" if PPC_STD_MMU && CRASH_DUMP | ||
| 705 | default "0x00000000" | ||
| 706 | |||
| 707 | config PHYSICAL_ALIGN | ||
| 708 | hex | ||
| 709 | default "0x10000000" if FSL_BOOKE | ||
| 710 | help | ||
| 711 | This value puts the alignment restrictions on physical address | ||
| 712 | where kernel is loaded and run from. Kernel is compiled for an | ||
| 713 | address which meets above alignment restriction. | ||
| 714 | |||
| 674 | config TASK_SIZE_BOOL | 715 | config TASK_SIZE_BOOL |
| 675 | bool "Set custom user task size" | 716 | bool "Set custom user task size" |
| 676 | depends on ADVANCED_OPTIONS | 717 | depends on ADVANCED_OPTIONS |
| @@ -717,9 +758,17 @@ config PIN_TLB | |||
| 717 | endmenu | 758 | endmenu |
| 718 | 759 | ||
| 719 | if PPC64 | 760 | if PPC64 |
| 761 | config PAGE_OFFSET | ||
| 762 | hex | ||
| 763 | default "0xc000000000000000" | ||
| 720 | config KERNEL_START | 764 | config KERNEL_START |
| 721 | hex | 765 | hex |
| 766 | default "0xc000000002000000" if CRASH_DUMP | ||
| 722 | default "0xc000000000000000" | 767 | default "0xc000000000000000" |
| 768 | config PHYSICAL_START | ||
| 769 | hex | ||
| 770 | default "0x02000000" if CRASH_DUMP | ||
| 771 | default "0x00000000" | ||
| 723 | endif | 772 | endif |
| 724 | 773 | ||
| 725 | source "net/Kconfig" | 774 | source "net/Kconfig" |
diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore index 5ef2bdf8d189..2347294ff35b 100644 --- a/arch/powerpc/boot/.gitignore +++ b/arch/powerpc/boot/.gitignore | |||
| @@ -27,6 +27,7 @@ zImage.chrp | |||
| 27 | zImage.coff | 27 | zImage.coff |
| 28 | zImage.coff.lds | 28 | zImage.coff.lds |
| 29 | zImage.ep* | 29 | zImage.ep* |
| 30 | zImage.iseries | ||
| 30 | zImage.*lds | 31 | zImage.*lds |
| 31 | zImage.miboot | 32 | zImage.miboot |
| 32 | zImage.pmac | 33 | zImage.pmac |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 5ba50c673390..7822d25c9d31 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
| @@ -40,7 +40,7 @@ $(obj)/ebony.o: BOOTCFLAGS += -mcpu=405 | |||
| 40 | $(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405 | 40 | $(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405 |
| 41 | $(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405 | 41 | $(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405 |
| 42 | $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405 | 42 | $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405 |
| 43 | $(obj)/virtex405-head.o: BOOTCFLAGS += -mcpu=405 | 43 | $(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405 |
| 44 | 44 | ||
| 45 | 45 | ||
| 46 | zlib := inffast.c inflate.c inftrees.c | 46 | zlib := inffast.c inflate.c inftrees.c |
diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts index 6f3d38a1554f..39634124929b 100644 --- a/arch/powerpc/boot/dts/canyonlands.dts +++ b/arch/powerpc/boot/dts/canyonlands.dts | |||
| @@ -142,8 +142,45 @@ | |||
| 142 | #address-cells = <2>; | 142 | #address-cells = <2>; |
| 143 | #size-cells = <1>; | 143 | #size-cells = <1>; |
| 144 | clock-frequency = <0>; /* Filled in by U-Boot */ | 144 | clock-frequency = <0>; /* Filled in by U-Boot */ |
| 145 | /* ranges property is supplied by U-Boot */ | ||
| 145 | interrupts = <6 4>; | 146 | interrupts = <6 4>; |
| 146 | interrupt-parent = <&UIC1>; | 147 | interrupt-parent = <&UIC1>; |
| 148 | |||
| 149 | nor_flash@0,0 { | ||
| 150 | compatible = "amd,s29gl512n", "cfi-flash"; | ||
| 151 | bank-width = <2>; | ||
| 152 | reg = <0 000000 4000000>; | ||
| 153 | #address-cells = <1>; | ||
| 154 | #size-cells = <1>; | ||
| 155 | partition@0 { | ||
| 156 | label = "kernel"; | ||
| 157 | reg = <0 1e0000>; | ||
| 158 | }; | ||
| 159 | partition@1e0000 { | ||
| 160 | label = "dtb"; | ||
| 161 | reg = <1e0000 20000>; | ||
| 162 | }; | ||
| 163 | partition@200000 { | ||
| 164 | label = "ramdisk"; | ||
| 165 | reg = <200000 1400000>; | ||
| 166 | }; | ||
| 167 | partition@1600000 { | ||
| 168 | label = "jffs2"; | ||
| 169 | reg = <1600000 400000>; | ||
| 170 | }; | ||
| 171 | partition@1a00000 { | ||
| 172 | label = "user"; | ||
| 173 | reg = <1a00000 2560000>; | ||
| 174 | }; | ||
| 175 | partition@3f60000 { | ||
| 176 | label = "env"; | ||
| 177 | reg = <3f60000 40000>; | ||
| 178 | }; | ||
| 179 | partition@3fa0000 { | ||
| 180 | label = "u-boot"; | ||
| 181 | reg = <3fa0000 60000>; | ||
| 182 | }; | ||
| 183 | }; | ||
| 147 | }; | 184 | }; |
| 148 | 185 | ||
| 149 | UART0: serial@ef600300 { | 186 | UART0: serial@ef600300 { |
diff --git a/arch/powerpc/boot/dts/glacier.dts b/arch/powerpc/boot/dts/glacier.dts index 958a5ca53d35..0f2fc077d8db 100644 --- a/arch/powerpc/boot/dts/glacier.dts +++ b/arch/powerpc/boot/dts/glacier.dts | |||
| @@ -145,8 +145,45 @@ | |||
| 145 | #address-cells = <2>; | 145 | #address-cells = <2>; |
| 146 | #size-cells = <1>; | 146 | #size-cells = <1>; |
| 147 | clock-frequency = <0>; /* Filled in by U-Boot */ | 147 | clock-frequency = <0>; /* Filled in by U-Boot */ |
| 148 | /* ranges property is supplied by U-Boot */ | ||
| 148 | interrupts = <6 4>; | 149 | interrupts = <6 4>; |
| 149 | interrupt-parent = <&UIC1>; | 150 | interrupt-parent = <&UIC1>; |
| 151 | |||
| 152 | nor_flash@0,0 { | ||
| 153 | compatible = "amd,s29gl512n", "cfi-flash"; | ||
| 154 | bank-width = <2>; | ||
| 155 | reg = <0 000000 4000000>; | ||
| 156 | #address-cells = <1>; | ||
| 157 | #size-cells = <1>; | ||
| 158 | partition@0 { | ||
| 159 | label = "kernel"; | ||
| 160 | reg = <0 1e0000>; | ||
| 161 | }; | ||
| 162 | partition@1e0000 { | ||
| 163 | label = "dtb"; | ||
| 164 | reg = <1e0000 20000>; | ||
| 165 | }; | ||
| 166 | partition@200000 { | ||
| 167 | label = "ramdisk"; | ||
| 168 | reg = <200000 1400000>; | ||
| 169 | }; | ||
| 170 | partition@1600000 { | ||
| 171 | label = "jffs2"; | ||
| 172 | reg = <1600000 400000>; | ||
| 173 | }; | ||
| 174 | partition@1a00000 { | ||
| 175 | label = "user"; | ||
| 176 | reg = <1a00000 2560000>; | ||
| 177 | }; | ||
| 178 | partition@3f60000 { | ||
| 179 | label = "env"; | ||
| 180 | reg = <3f60000 40000>; | ||
| 181 | }; | ||
| 182 | partition@3fa0000 { | ||
| 183 | label = "u-boot"; | ||
| 184 | reg = <3fa0000 60000>; | ||
| 185 | }; | ||
| 186 | }; | ||
| 150 | }; | 187 | }; |
| 151 | 188 | ||
| 152 | UART0: serial@ef600300 { | 189 | UART0: serial@ef600300 { |
diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c index aef3bdc89160..8c9ead94be06 100644 --- a/arch/powerpc/boot/ns16550.c +++ b/arch/powerpc/boot/ns16550.c | |||
| @@ -55,10 +55,15 @@ static u8 ns16550_tstc(void) | |||
| 55 | int ns16550_console_init(void *devp, struct serial_console_data *scdp) | 55 | int ns16550_console_init(void *devp, struct serial_console_data *scdp) |
| 56 | { | 56 | { |
| 57 | int n; | 57 | int n; |
| 58 | u32 reg_offset; | ||
| 58 | 59 | ||
| 59 | if (dt_get_virtual_reg(devp, (void **)®_base, 1) < 1) | 60 | if (dt_get_virtual_reg(devp, (void **)®_base, 1) < 1) |
| 60 | return -1; | 61 | return -1; |
| 61 | 62 | ||
| 63 | n = getprop(devp, "reg-offset", ®_offset, sizeof(reg_offset)); | ||
| 64 | if (n == sizeof(reg_offset)) | ||
| 65 | reg_base += reg_offset; | ||
| 66 | |||
| 62 | n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift)); | 67 | n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift)); |
| 63 | if (n != sizeof(reg_shift)) | 68 | if (n != sizeof(reg_shift)) |
| 64 | reg_shift = 0; | 69 | reg_shift = 0; |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index ce1e8d24e747..9177b21b1a95 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
| @@ -106,4 +106,13 @@ PHONY += systbl_chk | |||
| 106 | systbl_chk: $(src)/systbl_chk.sh $(obj)/systbl_chk.i | 106 | systbl_chk: $(src)/systbl_chk.sh $(obj)/systbl_chk.i |
| 107 | $(call cmd,systbl_chk) | 107 | $(call cmd,systbl_chk) |
| 108 | 108 | ||
| 109 | $(obj)/built-in.o: prom_init_check | ||
| 110 | |||
| 111 | quiet_cmd_prom_init_check = CALL $< | ||
| 112 | cmd_prom_init_check = $(CONFIG_SHELL) $< "$(NM)" "$(obj)/prom_init.o" | ||
| 113 | |||
| 114 | PHONY += prom_init_check | ||
| 115 | prom_init_check: $(src)/prom_init_check.sh $(obj)/prom_init.o | ||
| 116 | $(call cmd,prom_init_check) | ||
| 117 | |||
| 109 | clean-files := vmlinux.lds | 118 | clean-files := vmlinux.lds |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 292c6d8db0e1..adf1d09d726f 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
| @@ -93,10 +93,7 @@ int main(void) | |||
| 93 | DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags)); | 93 | DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags)); |
| 94 | DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); | 94 | DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); |
| 95 | DEFINE(TI_TASK, offsetof(struct thread_info, task)); | 95 | DEFINE(TI_TASK, offsetof(struct thread_info, task)); |
| 96 | #ifdef CONFIG_PPC32 | ||
| 97 | DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain)); | ||
| 98 | DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); | 96 | DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); |
| 99 | #endif /* CONFIG_PPC32 */ | ||
| 100 | 97 | ||
| 101 | #ifdef CONFIG_PPC64 | 98 | #ifdef CONFIG_PPC64 |
| 102 | DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size)); | 99 | DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size)); |
| @@ -165,13 +162,9 @@ int main(void) | |||
| 165 | 162 | ||
| 166 | /* Interrupt register frame */ | 163 | /* Interrupt register frame */ |
| 167 | DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); | 164 | DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); |
| 168 | #ifndef CONFIG_PPC64 | 165 | DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE); |
| 169 | DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); | 166 | #ifdef CONFIG_PPC64 |
| 170 | #else /* CONFIG_PPC64 */ | ||
| 171 | DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); | 167 | DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); |
| 172 | /* 288 = # of volatile regs, int & fp, for leaf routines */ | ||
| 173 | /* which do not stack a frame. See the PPC64 ABI. */ | ||
| 174 | DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 288); | ||
| 175 | /* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */ | 168 | /* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */ |
| 176 | DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); | 169 | DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); |
| 177 | DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); | 170 | DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); |
diff --git a/arch/powerpc/kernel/cpu_setup_44x.S b/arch/powerpc/kernel/cpu_setup_44x.S index 5465e8de0e61..e3623e3e3451 100644 --- a/arch/powerpc/kernel/cpu_setup_44x.S +++ b/arch/powerpc/kernel/cpu_setup_44x.S | |||
| @@ -33,7 +33,6 @@ _GLOBAL(__setup_cpu_440grx) | |||
| 33 | mtlr r4 | 33 | mtlr r4 |
| 34 | blr | 34 | blr |
| 35 | _GLOBAL(__setup_cpu_460ex) | 35 | _GLOBAL(__setup_cpu_460ex) |
| 36 | _GLOBAL(__setup_cpu_460gt) | ||
| 37 | b __init_fpu_44x | 36 | b __init_fpu_44x |
| 38 | _GLOBAL(__setup_cpu_440gx) | 37 | _GLOBAL(__setup_cpu_440gx) |
| 39 | _GLOBAL(__setup_cpu_440spe) | 38 | _GLOBAL(__setup_cpu_440spe) |
diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S index f1ee0b3f78f2..72d1d7395254 100644 --- a/arch/powerpc/kernel/cpu_setup_6xx.S +++ b/arch/powerpc/kernel/cpu_setup_6xx.S | |||
| @@ -17,7 +17,13 @@ | |||
| 17 | #include <asm/cache.h> | 17 | #include <asm/cache.h> |
| 18 | 18 | ||
| 19 | _GLOBAL(__setup_cpu_603) | 19 | _GLOBAL(__setup_cpu_603) |
| 20 | b setup_common_caches | 20 | mflr r4 |
| 21 | BEGIN_FTR_SECTION | ||
| 22 | bl __init_fpu_registers | ||
| 23 | END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE) | ||
| 24 | bl setup_common_caches | ||
| 25 | mtlr r4 | ||
| 26 | blr | ||
| 21 | _GLOBAL(__setup_cpu_604) | 27 | _GLOBAL(__setup_cpu_604) |
| 22 | mflr r4 | 28 | mflr r4 |
| 23 | bl setup_common_caches | 29 | bl setup_common_caches |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 26ffb44e2701..36080d4d1922 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
| @@ -37,7 +37,6 @@ extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec); | |||
| 37 | extern void __setup_cpu_440grx(unsigned long offset, struct cpu_spec* spec); | 37 | extern void __setup_cpu_440grx(unsigned long offset, struct cpu_spec* spec); |
| 38 | extern void __setup_cpu_440spe(unsigned long offset, struct cpu_spec* spec); | 38 | extern void __setup_cpu_440spe(unsigned long offset, struct cpu_spec* spec); |
| 39 | extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec); | 39 | extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec); |
| 40 | extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec); | ||
| 41 | extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); | 40 | extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); |
| 42 | extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); | 41 | extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); |
| 43 | extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec); | 42 | extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec); |
| @@ -1416,10 +1415,9 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 1416 | .pvr_value = 0x13020000, | 1415 | .pvr_value = 0x13020000, |
| 1417 | .cpu_name = "460GT", | 1416 | .cpu_name = "460GT", |
| 1418 | .cpu_features = CPU_FTRS_44X, | 1417 | .cpu_features = CPU_FTRS_44X, |
| 1419 | .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, | 1418 | .cpu_user_features = COMMON_USER_BOOKE, |
| 1420 | .icache_bsize = 32, | 1419 | .icache_bsize = 32, |
| 1421 | .dcache_bsize = 32, | 1420 | .dcache_bsize = 32, |
| 1422 | .cpu_setup = __setup_cpu_460gt, | ||
| 1423 | .machine_check = machine_check_440A, | 1421 | .machine_check = machine_check_440A, |
| 1424 | .platform = "ppc440", | 1422 | .platform = "ppc440", |
| 1425 | }, | 1423 | }, |
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 4ff744143566..e581524d85bc 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
| @@ -371,6 +371,17 @@ skpinv: addi r6,r6,1 /* Increment */ | |||
| 371 | 371 | ||
| 372 | bl early_init | 372 | bl early_init |
| 373 | 373 | ||
| 374 | #ifdef CONFIG_RELOCATABLE | ||
| 375 | lis r3,kernstart_addr@ha | ||
| 376 | la r3,kernstart_addr@l(r3) | ||
| 377 | #ifdef CONFIG_PHYS_64BIT | ||
| 378 | stw r23,0(r3) | ||
| 379 | stw r25,4(r3) | ||
| 380 | #else | ||
| 381 | stw r25,0(r3) | ||
| 382 | #endif | ||
| 383 | #endif | ||
| 384 | |||
| 374 | mfspr r3,SPRN_TLB1CFG | 385 | mfspr r3,SPRN_TLB1CFG |
| 375 | andi. r3,r3,0xfff | 386 | andi. r3,r3,0xfff |
| 376 | lis r4,num_tlbcam_entries@ha | 387 | lis r4,num_tlbcam_entries@ha |
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 9d2c56621f1e..92ccc6fcc5b0 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
| @@ -152,7 +152,7 @@ _GLOBAL(low_choose_750fx_pll) | |||
| 152 | mtspr SPRN_HID1,r4 | 152 | mtspr SPRN_HID1,r4 |
| 153 | 153 | ||
| 154 | /* Store new HID1 image */ | 154 | /* Store new HID1 image */ |
| 155 | rlwinm r6,r1,0,0,18 | 155 | rlwinm r6,r1,0,0,(31-THREAD_SHIFT) |
| 156 | lwz r6,TI_CPU(r6) | 156 | lwz r6,TI_CPU(r6) |
| 157 | slwi r6,r6,2 | 157 | slwi r6,r6,2 |
| 158 | addis r6,r6,nap_save_hid1@ha | 158 | addis r6,r6,nap_save_hid1@ha |
| @@ -281,7 +281,7 @@ _GLOBAL(_tlbia) | |||
| 281 | #endif /* CONFIG_SMP */ | 281 | #endif /* CONFIG_SMP */ |
| 282 | #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */ | 282 | #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */ |
| 283 | #if defined(CONFIG_SMP) | 283 | #if defined(CONFIG_SMP) |
| 284 | rlwinm r8,r1,0,0,18 | 284 | rlwinm r8,r1,0,0,(31-THREAD_SHIFT) |
| 285 | lwz r8,TI_CPU(r8) | 285 | lwz r8,TI_CPU(r8) |
| 286 | oris r8,r8,10 | 286 | oris r8,r8,10 |
| 287 | mfmsr r10 | 287 | mfmsr r10 |
| @@ -377,7 +377,7 @@ _GLOBAL(_tlbie) | |||
| 377 | #endif /* CONFIG_SMP */ | 377 | #endif /* CONFIG_SMP */ |
| 378 | #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */ | 378 | #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */ |
| 379 | #if defined(CONFIG_SMP) | 379 | #if defined(CONFIG_SMP) |
| 380 | rlwinm r8,r1,0,0,18 | 380 | rlwinm r8,r1,0,0,(31-THREAD_SHIFT) |
| 381 | lwz r8,TI_CPU(r8) | 381 | lwz r8,TI_CPU(r8) |
| 382 | oris r8,r8,11 | 382 | oris r8,r8,11 |
| 383 | mfmsr r10 | 383 | mfmsr r10 |
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index a3c491e88a72..942951e76586 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
| @@ -27,23 +27,11 @@ | |||
| 27 | 27 | ||
| 28 | .text | 28 | .text |
| 29 | 29 | ||
| 30 | _GLOBAL(get_msr) | ||
| 31 | mfmsr r3 | ||
| 32 | blr | ||
| 33 | |||
| 34 | _GLOBAL(get_srr0) | ||
| 35 | mfsrr0 r3 | ||
| 36 | blr | ||
| 37 | |||
| 38 | _GLOBAL(get_srr1) | ||
| 39 | mfsrr1 r3 | ||
| 40 | blr | ||
| 41 | |||
| 42 | #ifdef CONFIG_IRQSTACKS | 30 | #ifdef CONFIG_IRQSTACKS |
| 43 | _GLOBAL(call_do_softirq) | 31 | _GLOBAL(call_do_softirq) |
| 44 | mflr r0 | 32 | mflr r0 |
| 45 | std r0,16(r1) | 33 | std r0,16(r1) |
| 46 | stdu r1,THREAD_SIZE-112(r3) | 34 | stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3) |
| 47 | mr r1,r3 | 35 | mr r1,r3 |
| 48 | bl .__do_softirq | 36 | bl .__do_softirq |
| 49 | ld r1,0(r1) | 37 | ld r1,0(r1) |
| @@ -56,7 +44,7 @@ _GLOBAL(call_handle_irq) | |||
| 56 | mflr r0 | 44 | mflr r0 |
| 57 | std r0,16(r1) | 45 | std r0,16(r1) |
| 58 | mtctr r8 | 46 | mtctr r8 |
| 59 | stdu r1,THREAD_SIZE-112(r5) | 47 | stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5) |
| 60 | mr r1,r5 | 48 | mr r1,r5 |
| 61 | bctrl | 49 | bctrl |
| 62 | ld r1,0(r1) | 50 | ld r1,0(r1) |
| @@ -599,7 +587,7 @@ _GLOBAL(kexec_sequence) | |||
| 599 | std r0,16(r1) | 587 | std r0,16(r1) |
| 600 | 588 | ||
| 601 | /* switch stacks to newstack -- &kexec_stack.stack */ | 589 | /* switch stacks to newstack -- &kexec_stack.stack */ |
| 602 | stdu r1,THREAD_SIZE-112(r3) | 590 | stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3) |
| 603 | mr r1,r3 | 591 | mr r1,r3 |
| 604 | 592 | ||
| 605 | li r0,0 | 593 | li r0,0 |
| @@ -616,7 +604,7 @@ _GLOBAL(kexec_sequence) | |||
| 616 | std r26,-48(r1) | 604 | std r26,-48(r1) |
| 617 | std r25,-56(r1) | 605 | std r25,-56(r1) |
| 618 | 606 | ||
| 619 | stdu r1,-112-64(r1) | 607 | stdu r1,-STACK_FRAME_OVERHEAD-64(r1) |
| 620 | 608 | ||
| 621 | /* save args into preserved regs */ | 609 | /* save args into preserved regs */ |
| 622 | mr r31,r3 /* newstack (both) */ | 610 | mr r31,r3 /* newstack (both) */ |
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index fb698d47082d..e79ad8afda07 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c | |||
| @@ -275,6 +275,8 @@ static int __devinit of_pci_phb_probe(struct of_device *dev, | |||
| 275 | 275 | ||
| 276 | /* Scan the bus */ | 276 | /* Scan the bus */ |
| 277 | scan_phb(phb); | 277 | scan_phb(phb); |
| 278 | if (phb->bus == NULL) | ||
| 279 | return -ENXIO; | ||
| 278 | 280 | ||
| 279 | /* Claim resources. This might need some rework as well depending | 281 | /* Claim resources. This might need some rework as well depending |
| 280 | * wether we are doing probe-only or not, like assigning unassigned | 282 | * wether we are doing probe-only or not, like assigning unassigned |
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index ac163bd46cfd..c9bf17eec31b 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
| @@ -7,17 +7,11 @@ | |||
| 7 | * 2 of the License, or (at your option) any later version. | 7 | * 2 of the License, or (at your option) any later version. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/types.h> | ||
| 11 | #include <linux/threads.h> | 10 | #include <linux/threads.h> |
| 12 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 13 | 12 | ||
| 14 | #include <asm/processor.h> | ||
| 15 | #include <asm/ptrace.h> | ||
| 16 | #include <asm/page.h> | ||
| 17 | #include <asm/lppaca.h> | 13 | #include <asm/lppaca.h> |
| 18 | #include <asm/paca.h> | 14 | #include <asm/paca.h> |
| 19 | #include <asm/mmu.h> | ||
| 20 | |||
| 21 | 15 | ||
| 22 | /* This symbol is provided by the linker - let it fill in the paca | 16 | /* This symbol is provided by the linker - let it fill in the paca |
| 23 | * field correctly */ | 17 | * field correctly */ |
| @@ -65,60 +59,29 @@ struct slb_shadow slb_shadow[] __cacheline_aligned = { | |||
| 65 | * processors. The processor VPD array needs one entry per physical | 59 | * processors. The processor VPD array needs one entry per physical |
| 66 | * processor (not thread). | 60 | * processor (not thread). |
| 67 | */ | 61 | */ |
| 68 | #define PACA_INIT(number) \ | 62 | struct paca_struct paca[NR_CPUS]; |
| 69 | { \ | ||
| 70 | .lppaca_ptr = &lppaca[number], \ | ||
| 71 | .lock_token = 0x8000, \ | ||
| 72 | .paca_index = (number), /* Paca Index */ \ | ||
| 73 | .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \ | ||
| 74 | .hw_cpu_id = 0xffff, \ | ||
| 75 | .slb_shadow_ptr = &slb_shadow[number], \ | ||
| 76 | .__current = &init_task, \ | ||
| 77 | } | ||
| 78 | |||
| 79 | struct paca_struct paca[] = { | ||
| 80 | PACA_INIT(0), | ||
| 81 | #if NR_CPUS > 1 | ||
| 82 | PACA_INIT( 1), PACA_INIT( 2), PACA_INIT( 3), | ||
| 83 | #if NR_CPUS > 4 | ||
| 84 | PACA_INIT( 4), PACA_INIT( 5), PACA_INIT( 6), PACA_INIT( 7), | ||
| 85 | #if NR_CPUS > 8 | ||
| 86 | PACA_INIT( 8), PACA_INIT( 9), PACA_INIT( 10), PACA_INIT( 11), | ||
| 87 | PACA_INIT( 12), PACA_INIT( 13), PACA_INIT( 14), PACA_INIT( 15), | ||
| 88 | PACA_INIT( 16), PACA_INIT( 17), PACA_INIT( 18), PACA_INIT( 19), | ||
| 89 | PACA_INIT( 20), PACA_INIT( 21), PACA_INIT( 22), PACA_INIT( 23), | ||
| 90 | PACA_INIT( 24), PACA_INIT( 25), PACA_INIT( 26), PACA_INIT( 27), | ||
| 91 | PACA_INIT( 28), PACA_INIT( 29), PACA_INIT( 30), PACA_INIT( 31), | ||
| 92 | #if NR_CPUS > 32 | ||
| 93 | PACA_INIT( 32), PACA_INIT( 33), PACA_INIT( 34), PACA_INIT( 35), | ||
| 94 | PACA_INIT( 36), PACA_INIT( 37), PACA_INIT( 38), PACA_INIT( 39), | ||
| 95 | PACA_INIT( 40), PACA_INIT( 41), PACA_INIT( 42), PACA_INIT( 43), | ||
| 96 | PACA_INIT( 44), PACA_INIT( 45), PACA_INIT( 46), PACA_INIT( 47), | ||
| 97 | PACA_INIT( 48), PACA_INIT( 49), PACA_INIT( 50), PACA_INIT( 51), | ||
| 98 | PACA_INIT( 52), PACA_INIT( 53), PACA_INIT( 54), PACA_INIT( 55), | ||
| 99 | PACA_INIT( 56), PACA_INIT( 57), PACA_INIT( 58), PACA_INIT( 59), | ||
| 100 | PACA_INIT( 60), PACA_INIT( 61), PACA_INIT( 62), PACA_INIT( 63), | ||
| 101 | #if NR_CPUS > 64 | ||
| 102 | PACA_INIT( 64), PACA_INIT( 65), PACA_INIT( 66), PACA_INIT( 67), | ||
| 103 | PACA_INIT( 68), PACA_INIT( 69), PACA_INIT( 70), PACA_INIT( 71), | ||
| 104 | PACA_INIT( 72), PACA_INIT( 73), PACA_INIT( 74), PACA_INIT( 75), | ||
| 105 | PACA_INIT( 76), PACA_INIT( 77), PACA_INIT( 78), PACA_INIT( 79), | ||
| 106 | PACA_INIT( 80), PACA_INIT( 81), PACA_INIT( 82), PACA_INIT( 83), | ||
| 107 | PACA_INIT( 84), PACA_INIT( 85), PACA_INIT( 86), PACA_INIT( 87), | ||
| 108 | PACA_INIT( 88), PACA_INIT( 89), PACA_INIT( 90), PACA_INIT( 91), | ||
| 109 | PACA_INIT( 92), PACA_INIT( 93), PACA_INIT( 94), PACA_INIT( 95), | ||
| 110 | PACA_INIT( 96), PACA_INIT( 97), PACA_INIT( 98), PACA_INIT( 99), | ||
| 111 | PACA_INIT(100), PACA_INIT(101), PACA_INIT(102), PACA_INIT(103), | ||
| 112 | PACA_INIT(104), PACA_INIT(105), PACA_INIT(106), PACA_INIT(107), | ||
| 113 | PACA_INIT(108), PACA_INIT(109), PACA_INIT(110), PACA_INIT(111), | ||
| 114 | PACA_INIT(112), PACA_INIT(113), PACA_INIT(114), PACA_INIT(115), | ||
| 115 | PACA_INIT(116), PACA_INIT(117), PACA_INIT(118), PACA_INIT(119), | ||
| 116 | PACA_INIT(120), PACA_INIT(121), PACA_INIT(122), PACA_INIT(123), | ||
| 117 | PACA_INIT(124), PACA_INIT(125), PACA_INIT(126), PACA_INIT(127), | ||
| 118 | #endif | ||
| 119 | #endif | ||
| 120 | #endif | ||
| 121 | #endif | ||
| 122 | #endif | ||
| 123 | }; | ||
| 124 | EXPORT_SYMBOL(paca); | 63 | EXPORT_SYMBOL(paca); |
| 64 | |||
| 65 | void __init initialise_pacas(void) | ||
| 66 | { | ||
| 67 | int cpu; | ||
| 68 | |||
| 69 | /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB | ||
| 70 | * of the TOC can be addressed using a single machine instruction. | ||
| 71 | */ | ||
| 72 | unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL; | ||
| 73 | |||
| 74 | /* Can't use for_each_*_cpu, as they aren't functional yet */ | ||
| 75 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | ||
| 76 | struct paca_struct *new_paca = &paca[cpu]; | ||
| 77 | |||
| 78 | new_paca->lppaca_ptr = &lppaca[cpu]; | ||
| 79 | new_paca->lock_token = 0x8000; | ||
| 80 | new_paca->paca_index = cpu; | ||
| 81 | new_paca->kernel_toc = kernel_toc; | ||
| 82 | new_paca->hw_cpu_id = 0xffff; | ||
| 83 | new_paca->slb_shadow_ptr = &slb_shadow[cpu]; | ||
| 84 | new_paca->__current = &init_task; | ||
| 85 | |||
| 86 | } | ||
| 87 | } | ||
diff --git a/arch/powerpc/kernel/ppc32.h b/arch/powerpc/kernel/ppc32.h index fda05e2211d6..90e562771791 100644 --- a/arch/powerpc/kernel/ppc32.h +++ b/arch/powerpc/kernel/ppc32.h | |||
| @@ -135,6 +135,4 @@ struct ucontext32 { | |||
| 135 | struct mcontext32 uc_mcontext; | 135 | struct mcontext32 uc_mcontext; |
| 136 | }; | 136 | }; |
| 137 | 137 | ||
| 138 | extern int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s); | ||
| 139 | |||
| 140 | #endif /* _PPC64_PPC32_H */ | 138 | #endif /* _PPC64_PPC32_H */ |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 703100d5e458..6caad17ea72e 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -1033,3 +1033,34 @@ void ppc64_runlatch_off(void) | |||
| 1033 | } | 1033 | } |
| 1034 | } | 1034 | } |
| 1035 | #endif | 1035 | #endif |
| 1036 | |||
| 1037 | #if THREAD_SHIFT < PAGE_SHIFT | ||
| 1038 | |||
| 1039 | static struct kmem_cache *thread_info_cache; | ||
| 1040 | |||
| 1041 | struct thread_info *alloc_thread_info(struct task_struct *tsk) | ||
| 1042 | { | ||
| 1043 | struct thread_info *ti; | ||
| 1044 | |||
| 1045 | ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL); | ||
| 1046 | if (unlikely(ti == NULL)) | ||
| 1047 | return NULL; | ||
| 1048 | #ifdef CONFIG_DEBUG_STACK_USAGE | ||
| 1049 | memset(ti, 0, THREAD_SIZE); | ||
| 1050 | #endif | ||
| 1051 | return ti; | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | void free_thread_info(struct thread_info *ti) | ||
| 1055 | { | ||
| 1056 | kmem_cache_free(thread_info_cache, ti); | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | void thread_info_cache_init(void) | ||
| 1060 | { | ||
| 1061 | thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE, | ||
| 1062 | THREAD_SIZE, 0, NULL); | ||
| 1063 | BUG_ON(thread_info_cache == NULL); | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | #endif /* THREAD_SHIFT < PAGE_SHIFT */ | ||
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 3bfe7837e820..2aefe2a4129a 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #include <asm/pci-bridge.h> | 53 | #include <asm/pci-bridge.h> |
| 54 | #include <asm/phyp_dump.h> | 54 | #include <asm/phyp_dump.h> |
| 55 | #include <asm/kexec.h> | 55 | #include <asm/kexec.h> |
| 56 | #include <mm/mmu_decl.h> | ||
| 56 | 57 | ||
| 57 | #ifdef DEBUG | 58 | #ifdef DEBUG |
| 58 | #define DBG(fmt...) printk(KERN_ERR fmt) | 59 | #define DBG(fmt...) printk(KERN_ERR fmt) |
| @@ -978,7 +979,10 @@ static int __init early_init_dt_scan_memory(unsigned long node, | |||
| 978 | } | 979 | } |
| 979 | #endif | 980 | #endif |
| 980 | lmb_add(base, size); | 981 | lmb_add(base, size); |
| 982 | |||
| 983 | memstart_addr = min((u64)memstart_addr, base); | ||
| 981 | } | 984 | } |
| 985 | |||
| 982 | return 0; | 986 | return 0; |
| 983 | } | 987 | } |
| 984 | 988 | ||
diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh new file mode 100644 index 000000000000..8e24fc1821e8 --- /dev/null +++ b/arch/powerpc/kernel/prom_init_check.sh | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | # | ||
| 3 | # Copyright © 2008 IBM Corporation | ||
| 4 | # | ||
| 5 | # This program is free software; you can redistribute it and/or | ||
| 6 | # modify it under the terms of the GNU General Public License | ||
| 7 | # as published by the Free Software Foundation; either version | ||
| 8 | # 2 of the License, or (at your option) any later version. | ||
| 9 | |||
| 10 | # This script checks prom_init.o to see what external symbols it | ||
| 11 | # is using, if it finds symbols not in the whitelist it returns | ||
| 12 | # an error. The point of this is to discourage people from | ||
| 13 | # intentionally or accidentally adding new code to prom_init.c | ||
| 14 | # which has side effects on other parts of the kernel. | ||
| 15 | |||
| 16 | # If you really need to reference something from prom_init.o add | ||
| 17 | # it to the list below: | ||
| 18 | |||
| 19 | WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush | ||
| 20 | _end enter_prom memcpy memset reloc_offset __secondary_hold | ||
| 21 | __secondary_hold_acknowledge __secondary_hold_spinloop __start | ||
| 22 | strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224 | ||
| 23 | reloc_got2" | ||
| 24 | |||
| 25 | NM="$1" | ||
| 26 | OBJ="$2" | ||
| 27 | |||
| 28 | ERROR=0 | ||
| 29 | |||
| 30 | for UNDEF in $($NM -u $OBJ | awk '{print $2}') | ||
| 31 | do | ||
| 32 | # On 64-bit nm gives us the function descriptors, which have | ||
| 33 | # a leading . on the name, so strip it off here. | ||
| 34 | UNDEF="${UNDEF#.}" | ||
| 35 | |||
| 36 | if [ $KBUILD_VERBOSE ]; then | ||
| 37 | if [ $KBUILD_VERBOSE -ne 0 ]; then | ||
| 38 | echo "Checking prom_init.o symbol '$UNDEF'" | ||
| 39 | fi | ||
| 40 | fi | ||
| 41 | |||
| 42 | OK=0 | ||
| 43 | for WHITE in $WHITELIST | ||
| 44 | do | ||
| 45 | if [ "$UNDEF" = "$WHITE" ]; then | ||
| 46 | OK=1 | ||
| 47 | break | ||
| 48 | fi | ||
| 49 | done | ||
| 50 | |||
| 51 | if [ $OK -eq 0 ]; then | ||
| 52 | ERROR=1 | ||
| 53 | echo "Error: External symbol '$UNDEF' referenced" \ | ||
| 54 | "from prom_init.c" >&2 | ||
| 55 | fi | ||
| 56 | done | ||
| 57 | |||
| 58 | exit $ERROR | ||
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index 9d30e10970ac..4c1de6af4c09 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
| @@ -29,15 +29,12 @@ | |||
| 29 | #include <linux/security.h> | 29 | #include <linux/security.h> |
| 30 | #include <linux/signal.h> | 30 | #include <linux/signal.h> |
| 31 | #include <linux/compat.h> | 31 | #include <linux/compat.h> |
| 32 | #include <linux/elf.h> | ||
| 33 | 32 | ||
| 34 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
| 35 | #include <asm/page.h> | 34 | #include <asm/page.h> |
| 36 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
| 37 | #include <asm/system.h> | 36 | #include <asm/system.h> |
| 38 | 37 | ||
| 39 | #include "ppc32.h" | ||
| 40 | |||
| 41 | /* | 38 | /* |
| 42 | * does not yet catch signals sent when the child dies. | 39 | * does not yet catch signals sent when the child dies. |
| 43 | * in exit.c or in signal.c. | 40 | * in exit.c or in signal.c. |
| @@ -67,27 +64,6 @@ static long compat_ptrace_old(struct task_struct *child, long request, | |||
| 67 | return -EPERM; | 64 | return -EPERM; |
| 68 | } | 65 | } |
| 69 | 66 | ||
| 70 | static int compat_ptrace_getsiginfo(struct task_struct *child, compat_siginfo_t __user *data) | ||
| 71 | { | ||
| 72 | siginfo_t lastinfo; | ||
| 73 | int error = -ESRCH; | ||
| 74 | |||
| 75 | read_lock(&tasklist_lock); | ||
| 76 | if (likely(child->sighand != NULL)) { | ||
| 77 | error = -EINVAL; | ||
| 78 | spin_lock_irq(&child->sighand->siglock); | ||
| 79 | if (likely(child->last_siginfo != NULL)) { | ||
| 80 | lastinfo = *child->last_siginfo; | ||
| 81 | error = 0; | ||
| 82 | } | ||
| 83 | spin_unlock_irq(&child->sighand->siglock); | ||
| 84 | } | ||
| 85 | read_unlock(&tasklist_lock); | ||
| 86 | if (!error) | ||
| 87 | return copy_siginfo_to_user32(data, &lastinfo); | ||
| 88 | return error; | ||
| 89 | } | ||
| 90 | |||
| 91 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | 67 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, |
| 92 | compat_ulong_t caddr, compat_ulong_t cdata) | 68 | compat_ulong_t caddr, compat_ulong_t cdata) |
| 93 | { | 69 | { |
| @@ -306,9 +282,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
| 306 | 0, PT_REGS_COUNT * sizeof(compat_long_t), | 282 | 0, PT_REGS_COUNT * sizeof(compat_long_t), |
| 307 | compat_ptr(data)); | 283 | compat_ptr(data)); |
| 308 | 284 | ||
| 309 | case PTRACE_GETSIGINFO: | ||
| 310 | return compat_ptrace_getsiginfo(child, compat_ptr(data)); | ||
| 311 | |||
| 312 | case PTRACE_GETFPREGS: | 285 | case PTRACE_GETFPREGS: |
| 313 | case PTRACE_SETFPREGS: | 286 | case PTRACE_SETFPREGS: |
| 314 | case PTRACE_GETVRREGS: | 287 | case PTRACE_GETVRREGS: |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 31ada9fdfc5c..dff6308d1b5e 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
| @@ -170,6 +170,9 @@ void __init setup_paca(int cpu) | |||
| 170 | 170 | ||
| 171 | void __init early_setup(unsigned long dt_ptr) | 171 | void __init early_setup(unsigned long dt_ptr) |
| 172 | { | 172 | { |
| 173 | /* Fill in any unititialised pacas */ | ||
| 174 | initialise_pacas(); | ||
| 175 | |||
| 173 | /* Identify CPU type */ | 176 | /* Identify CPU type */ |
| 174 | identify_cpu(0, mfspr(SPRN_PVR)); | 177 | identify_cpu(0, mfspr(SPRN_PVR)); |
| 175 | 178 | ||
| @@ -435,7 +438,7 @@ void __init setup_system(void) | |||
| 435 | printk("htab_address = 0x%p\n", htab_address); | 438 | printk("htab_address = 0x%p\n", htab_address); |
| 436 | printk("htab_hash_mask = 0x%lx\n", htab_hash_mask); | 439 | printk("htab_hash_mask = 0x%lx\n", htab_hash_mask); |
| 437 | #if PHYSICAL_START > 0 | 440 | #if PHYSICAL_START > 0 |
| 438 | printk("physical_start = 0x%x\n", PHYSICAL_START); | 441 | printk("physical_start = 0x%lx\n", PHYSICAL_START); |
| 439 | #endif | 442 | #endif |
| 440 | printk("-----------------------------------------------------\n"); | 443 | printk("-----------------------------------------------------\n"); |
| 441 | 444 | ||
diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c index e3638eeaaae7..962944038430 100644 --- a/arch/powerpc/kernel/stacktrace.c +++ b/arch/powerpc/kernel/stacktrace.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
| 14 | #include <linux/stacktrace.h> | 14 | #include <linux/stacktrace.h> |
| 15 | #include <asm/ptrace.h> | 15 | #include <asm/ptrace.h> |
| 16 | #include <asm/asm-offsets.h> | ||
| 17 | 16 | ||
| 18 | /* | 17 | /* |
| 19 | * Save stack-backtrace addresses into a stack_trace buffer. | 18 | * Save stack-backtrace addresses into a stack_trace buffer. |
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 7aad6203e411..7d6c9bb8c77f 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c | |||
| @@ -154,8 +154,8 @@ static void udbg_console_write(struct console *con, const char *s, | |||
| 154 | static struct console udbg_console = { | 154 | static struct console udbg_console = { |
| 155 | .name = "udbg", | 155 | .name = "udbg", |
| 156 | .write = udbg_console_write, | 156 | .write = udbg_console_write, |
| 157 | .flags = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT, | 157 | .flags = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT | CON_ANYTIME, |
| 158 | .index = -1, | 158 | .index = 0, |
| 159 | }; | 159 | }; |
| 160 | 160 | ||
| 161 | static int early_console_initialized; | 161 | static int early_console_initialized; |
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index ada249bf9779..ce10e2b1b902 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c | |||
| @@ -202,7 +202,7 @@ adjust_total_lowmem(void) | |||
| 202 | cam_max_size = max_lowmem_size; | 202 | cam_max_size = max_lowmem_size; |
| 203 | 203 | ||
| 204 | /* adjust lowmem size to max_lowmem_size */ | 204 | /* adjust lowmem size to max_lowmem_size */ |
| 205 | ram = min(max_lowmem_size, total_lowmem); | 205 | ram = min(max_lowmem_size, (phys_addr_t)total_lowmem); |
| 206 | 206 | ||
| 207 | /* Calculate CAM values */ | 207 | /* Calculate CAM values */ |
| 208 | __cam0 = 1UL << 2 * (__ilog2(ram) / 2); | 208 | __cam0 = 1UL << 2 * (__ilog2(ram) / 2); |
diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S index e10d76a860d3..ddeaf9e38ad5 100644 --- a/arch/powerpc/mm/hash_low_32.S +++ b/arch/powerpc/mm/hash_low_32.S | |||
| @@ -191,7 +191,7 @@ _GLOBAL(add_hash_page) | |||
| 191 | add r3,r3,r0 /* note create_hpte trims to 24 bits */ | 191 | add r3,r3,r0 /* note create_hpte trims to 24 bits */ |
| 192 | 192 | ||
| 193 | #ifdef CONFIG_SMP | 193 | #ifdef CONFIG_SMP |
| 194 | rlwinm r8,r1,0,0,18 /* use cpu number to make tag */ | 194 | rlwinm r8,r1,0,0,(31-THREAD_SHIFT) /* use cpu number to make tag */ |
| 195 | lwz r8,TI_CPU(r8) /* to go in mmu_hash_lock */ | 195 | lwz r8,TI_CPU(r8) /* to go in mmu_hash_lock */ |
| 196 | oris r8,r8,12 | 196 | oris r8,r8,12 |
| 197 | #endif /* CONFIG_SMP */ | 197 | #endif /* CONFIG_SMP */ |
| @@ -526,7 +526,7 @@ _GLOBAL(flush_hash_pages) | |||
| 526 | #ifdef CONFIG_SMP | 526 | #ifdef CONFIG_SMP |
| 527 | addis r9,r7,mmu_hash_lock@ha | 527 | addis r9,r7,mmu_hash_lock@ha |
| 528 | addi r9,r9,mmu_hash_lock@l | 528 | addi r9,r9,mmu_hash_lock@l |
| 529 | rlwinm r8,r1,0,0,18 | 529 | rlwinm r8,r1,0,0,(31-THREAD_SHIFT) |
| 530 | add r8,r8,r7 | 530 | add r8,r8,r7 |
| 531 | lwz r8,TI_CPU(r8) | 531 | lwz r8,TI_CPU(r8) |
| 532 | oris r8,r8,9 | 532 | oris r8,r8,9 |
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 47325f23c51f..1952b4d3fa7f 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
| @@ -59,7 +59,10 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | |||
| 59 | unsigned long total_memory; | 59 | unsigned long total_memory; |
| 60 | unsigned long total_lowmem; | 60 | unsigned long total_lowmem; |
| 61 | 61 | ||
| 62 | phys_addr_t memstart_addr; | 62 | phys_addr_t memstart_addr = (phys_addr_t)~0ull; |
| 63 | EXPORT_SYMBOL(memstart_addr); | ||
| 64 | phys_addr_t kernstart_addr; | ||
| 65 | EXPORT_SYMBOL(kernstart_addr); | ||
| 63 | phys_addr_t lowmem_end_addr; | 66 | phys_addr_t lowmem_end_addr; |
| 64 | 67 | ||
| 65 | int boot_mapsize; | 68 | int boot_mapsize; |
| @@ -68,14 +71,6 @@ unsigned long agp_special_page; | |||
| 68 | EXPORT_SYMBOL(agp_special_page); | 71 | EXPORT_SYMBOL(agp_special_page); |
| 69 | #endif | 72 | #endif |
| 70 | 73 | ||
| 71 | #ifdef CONFIG_HIGHMEM | ||
| 72 | pte_t *kmap_pte; | ||
| 73 | pgprot_t kmap_prot; | ||
| 74 | |||
| 75 | EXPORT_SYMBOL(kmap_prot); | ||
| 76 | EXPORT_SYMBOL(kmap_pte); | ||
| 77 | #endif | ||
| 78 | |||
| 79 | void MMU_init(void); | 74 | void MMU_init(void); |
| 80 | 75 | ||
| 81 | /* XXX should be in current.h -- paulus */ | 76 | /* XXX should be in current.h -- paulus */ |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 698bd000f98b..c5ac532a0161 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
| @@ -72,7 +72,8 @@ | |||
| 72 | #warning TASK_SIZE is smaller than it needs to be. | 72 | #warning TASK_SIZE is smaller than it needs to be. |
| 73 | #endif | 73 | #endif |
| 74 | 74 | ||
| 75 | phys_addr_t memstart_addr; | 75 | phys_addr_t memstart_addr = ~0; |
| 76 | phys_addr_t kernstart_addr; | ||
| 76 | 77 | ||
| 77 | void free_initmem(void) | 78 | void free_initmem(void) |
| 78 | { | 79 | { |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 16def4dcff6d..5ccb579b81e4 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | #include <asm/tlb.h> | 45 | #include <asm/tlb.h> |
| 46 | #include <asm/sections.h> | 46 | #include <asm/sections.h> |
| 47 | #include <asm/vdso.h> | 47 | #include <asm/vdso.h> |
| 48 | #include <asm/fixmap.h> | ||
| 48 | 49 | ||
| 49 | #include "mmu_decl.h" | 50 | #include "mmu_decl.h" |
| 50 | 51 | ||
| @@ -57,6 +58,20 @@ int init_bootmem_done; | |||
| 57 | int mem_init_done; | 58 | int mem_init_done; |
| 58 | unsigned long memory_limit; | 59 | unsigned long memory_limit; |
| 59 | 60 | ||
| 61 | #ifdef CONFIG_HIGHMEM | ||
| 62 | pte_t *kmap_pte; | ||
| 63 | pgprot_t kmap_prot; | ||
| 64 | |||
| 65 | EXPORT_SYMBOL(kmap_prot); | ||
| 66 | EXPORT_SYMBOL(kmap_pte); | ||
| 67 | |||
| 68 | static inline pte_t *virt_to_kpte(unsigned long vaddr) | ||
| 69 | { | ||
| 70 | return pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), | ||
| 71 | vaddr), vaddr), vaddr); | ||
| 72 | } | ||
| 73 | #endif | ||
| 74 | |||
| 60 | int page_is_ram(unsigned long pfn) | 75 | int page_is_ram(unsigned long pfn) |
| 61 | { | 76 | { |
| 62 | unsigned long paddr = (pfn << PAGE_SHIFT); | 77 | unsigned long paddr = (pfn << PAGE_SHIFT); |
| @@ -216,7 +231,7 @@ void __init do_init_bootmem(void) | |||
| 216 | unsigned long total_pages; | 231 | unsigned long total_pages; |
| 217 | int boot_mapsize; | 232 | int boot_mapsize; |
| 218 | 233 | ||
| 219 | max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT; | 234 | max_low_pfn = max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT; |
| 220 | total_pages = (lmb_end_of_DRAM() - memstart_addr) >> PAGE_SHIFT; | 235 | total_pages = (lmb_end_of_DRAM() - memstart_addr) >> PAGE_SHIFT; |
| 221 | #ifdef CONFIG_HIGHMEM | 236 | #ifdef CONFIG_HIGHMEM |
| 222 | total_pages = total_lowmem >> PAGE_SHIFT; | 237 | total_pages = total_lowmem >> PAGE_SHIFT; |
| @@ -232,7 +247,8 @@ void __init do_init_bootmem(void) | |||
| 232 | 247 | ||
| 233 | start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE); | 248 | start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE); |
| 234 | 249 | ||
| 235 | boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages); | 250 | min_low_pfn = MEMORY_START >> PAGE_SHIFT; |
| 251 | boot_mapsize = init_bootmem_node(NODE_DATA(0), start >> PAGE_SHIFT, min_low_pfn, max_low_pfn); | ||
| 236 | 252 | ||
| 237 | /* Add active regions with valid PFNs */ | 253 | /* Add active regions with valid PFNs */ |
| 238 | for (i = 0; i < lmb.memory.cnt; i++) { | 254 | for (i = 0; i < lmb.memory.cnt; i++) { |
| @@ -310,14 +326,19 @@ void __init paging_init(void) | |||
| 310 | unsigned long top_of_ram = lmb_end_of_DRAM(); | 326 | unsigned long top_of_ram = lmb_end_of_DRAM(); |
| 311 | unsigned long max_zone_pfns[MAX_NR_ZONES]; | 327 | unsigned long max_zone_pfns[MAX_NR_ZONES]; |
| 312 | 328 | ||
| 329 | #ifdef CONFIG_PPC32 | ||
| 330 | unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1); | ||
| 331 | unsigned long end = __fix_to_virt(FIX_HOLE); | ||
| 332 | |||
| 333 | for (; v < end; v += PAGE_SIZE) | ||
| 334 | map_page(v, 0, 0); /* XXX gross */ | ||
| 335 | #endif | ||
| 336 | |||
| 313 | #ifdef CONFIG_HIGHMEM | 337 | #ifdef CONFIG_HIGHMEM |
| 314 | map_page(PKMAP_BASE, 0, 0); /* XXX gross */ | 338 | map_page(PKMAP_BASE, 0, 0); /* XXX gross */ |
| 315 | pkmap_page_table = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k | 339 | pkmap_page_table = virt_to_kpte(PKMAP_BASE); |
| 316 | (PKMAP_BASE), PKMAP_BASE), PKMAP_BASE), PKMAP_BASE); | 340 | |
| 317 | map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */ | 341 | kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN)); |
| 318 | kmap_pte = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k | ||
| 319 | (KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), | ||
| 320 | KMAP_FIX_BEGIN); | ||
| 321 | kmap_prot = PAGE_KERNEL; | 342 | kmap_prot = PAGE_KERNEL; |
| 322 | #endif /* CONFIG_HIGHMEM */ | 343 | #endif /* CONFIG_HIGHMEM */ |
| 323 | 344 | ||
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 1efd631211ef..dc704da363eb 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/cpu.h> | 18 | #include <linux/cpu.h> |
| 19 | #include <linux/notifier.h> | 19 | #include <linux/notifier.h> |
| 20 | #include <linux/lmb.h> | 20 | #include <linux/lmb.h> |
| 21 | #include <linux/of.h> | ||
| 21 | #include <asm/sparsemem.h> | 22 | #include <asm/sparsemem.h> |
| 22 | #include <asm/prom.h> | 23 | #include <asm/prom.h> |
| 23 | #include <asm/system.h> | 24 | #include <asm/system.h> |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 64c44bcc68de..80d1babb230d 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | 29 | ||
| 30 | #include <asm/pgtable.h> | 30 | #include <asm/pgtable.h> |
| 31 | #include <asm/pgalloc.h> | 31 | #include <asm/pgalloc.h> |
| 32 | #include <asm/fixmap.h> | ||
| 32 | #include <asm/io.h> | 33 | #include <asm/io.h> |
| 33 | 34 | ||
| 34 | #include "mmu_decl.h" | 35 | #include "mmu_decl.h" |
| @@ -387,3 +388,25 @@ void kernel_map_pages(struct page *page, int numpages, int enable) | |||
| 387 | change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0)); | 388 | change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0)); |
| 388 | } | 389 | } |
| 389 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | 390 | #endif /* CONFIG_DEBUG_PAGEALLOC */ |
| 391 | |||
| 392 | static int fixmaps; | ||
| 393 | unsigned long FIXADDR_TOP = 0xfffff000; | ||
| 394 | EXPORT_SYMBOL(FIXADDR_TOP); | ||
| 395 | |||
| 396 | void __set_fixmap (enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags) | ||
| 397 | { | ||
| 398 | unsigned long address = __fix_to_virt(idx); | ||
| 399 | |||
| 400 | if (idx >= __end_of_fixed_addresses) { | ||
| 401 | BUG(); | ||
| 402 | return; | ||
| 403 | } | ||
| 404 | |||
| 405 | map_page(address, phys, flags); | ||
| 406 | fixmaps++; | ||
| 407 | } | ||
| 408 | |||
| 409 | void __this_fixmap_does_not_exist(void) | ||
| 410 | { | ||
| 411 | WARN_ON(1); | ||
| 412 | } | ||
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index f38c50b4ce56..87454c526973 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
| @@ -45,7 +45,6 @@ source "arch/powerpc/platforms/powermac/Kconfig" | |||
| 45 | source "arch/powerpc/platforms/prep/Kconfig" | 45 | source "arch/powerpc/platforms/prep/Kconfig" |
| 46 | source "arch/powerpc/platforms/maple/Kconfig" | 46 | source "arch/powerpc/platforms/maple/Kconfig" |
| 47 | source "arch/powerpc/platforms/pasemi/Kconfig" | 47 | source "arch/powerpc/platforms/pasemi/Kconfig" |
| 48 | source "arch/powerpc/platforms/celleb/Kconfig" | ||
| 49 | source "arch/powerpc/platforms/ps3/Kconfig" | 48 | source "arch/powerpc/platforms/ps3/Kconfig" |
| 50 | source "arch/powerpc/platforms/cell/Kconfig" | 49 | source "arch/powerpc/platforms/cell/Kconfig" |
| 51 | source "arch/powerpc/platforms/8xx/Kconfig" | 50 | source "arch/powerpc/platforms/8xx/Kconfig" |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 5fc7fac10e93..f7efaa925a13 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
| @@ -220,8 +220,8 @@ config SMP | |||
| 220 | If you don't know what to do here, say N. | 220 | If you don't know what to do here, say N. |
| 221 | 221 | ||
| 222 | config NR_CPUS | 222 | config NR_CPUS |
| 223 | int "Maximum number of CPUs (2-128)" | 223 | int "Maximum number of CPUs (2-1024)" |
| 224 | range 2 128 | 224 | range 2 1024 |
| 225 | depends on SMP | 225 | depends on SMP |
| 226 | default "32" if PPC64 | 226 | default "32" if PPC64 |
| 227 | default "4" | 227 | default "4" |
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index a984894466d9..423a0234dc31 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile | |||
| @@ -24,5 +24,4 @@ obj-$(CONFIG_PPC_MAPLE) += maple/ | |||
| 24 | obj-$(CONFIG_PPC_PASEMI) += pasemi/ | 24 | obj-$(CONFIG_PPC_PASEMI) += pasemi/ |
| 25 | obj-$(CONFIG_PPC_CELL) += cell/ | 25 | obj-$(CONFIG_PPC_CELL) += cell/ |
| 26 | obj-$(CONFIG_PPC_PS3) += ps3/ | 26 | obj-$(CONFIG_PPC_PS3) += ps3/ |
| 27 | obj-$(CONFIG_PPC_CELLEB) += celleb/ | ||
| 28 | obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/ | 27 | obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/ |
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 2f169991896d..3959fcfe731c 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig | |||
| @@ -25,6 +25,19 @@ config PPC_IBM_CELL_BLADE | |||
| 25 | select PPC_UDBG_16550 | 25 | select PPC_UDBG_16550 |
| 26 | select UDBG_RTAS_CONSOLE | 26 | select UDBG_RTAS_CONSOLE |
| 27 | 27 | ||
| 28 | config PPC_CELLEB | ||
| 29 | bool "Toshiba's Cell Reference Set 'Celleb' Architecture" | ||
| 30 | depends on PPC_MULTIPLATFORM && PPC64 | ||
| 31 | select PPC_CELL | ||
| 32 | select PPC_CELL_NATIVE | ||
| 33 | select PPC_RTAS | ||
| 34 | select PPC_INDIRECT_IO | ||
| 35 | select PPC_OF_PLATFORM_PCI | ||
| 36 | select HAS_TXX9_SERIAL | ||
| 37 | select PPC_UDBG_BEAT | ||
| 38 | select USB_OHCI_BIG_ENDIAN_MMIO | ||
| 39 | select USB_EHCI_BIG_ENDIAN_MMIO | ||
| 40 | |||
| 28 | menu "Cell Broadband Engine options" | 41 | menu "Cell Broadband Engine options" |
| 29 | depends on PPC_CELL | 42 | depends on PPC_CELL |
| 30 | 43 | ||
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index c89964c6fb1f..c2a7e4e5ddf9 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ | 1 | obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ |
| 2 | cbe_regs.o spider-pic.o \ | 2 | cbe_regs.o spider-pic.o \ |
| 3 | pervasive.o pmu.o io-workarounds.o | 3 | pervasive.o pmu.o io-workarounds.o \ |
| 4 | spider-pci.o | ||
| 4 | obj-$(CONFIG_CBE_RAS) += ras.o | 5 | obj-$(CONFIG_CBE_RAS) += ras.o |
| 5 | 6 | ||
| 6 | obj-$(CONFIG_CBE_THERM) += cbe_thermal.o | 7 | obj-$(CONFIG_CBE_THERM) += cbe_thermal.o |
| @@ -26,3 +27,20 @@ obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ | |||
| 26 | spufs/ | 27 | spufs/ |
| 27 | 28 | ||
| 28 | obj-$(CONFIG_PCI_MSI) += axon_msi.o | 29 | obj-$(CONFIG_PCI_MSI) += axon_msi.o |
| 30 | |||
| 31 | |||
| 32 | # celleb stuff | ||
| 33 | ifeq ($(CONFIG_PPC_CELLEB),y) | ||
| 34 | obj-y += celleb_setup.o \ | ||
| 35 | celleb_pci.o celleb_scc_epci.o \ | ||
| 36 | celleb_scc_pciex.o \ | ||
| 37 | celleb_scc_uhc.o \ | ||
| 38 | io-workarounds.o spider-pci.o \ | ||
| 39 | beat.o beat_htab.o beat_hvCall.o \ | ||
| 40 | beat_interrupt.o beat_iommu.o | ||
| 41 | |||
| 42 | obj-$(CONFIG_SMP) += beat_smp.o | ||
| 43 | obj-$(CONFIG_PPC_UDBG_BEAT) += beat_udbg.o | ||
| 44 | obj-$(CONFIG_SERIAL_TXX9) += celleb_scc_sio.o | ||
| 45 | obj-$(CONFIG_SPU_BASE) += beat_spu_priv1.o | ||
| 46 | endif | ||
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index d95e71dee91f..c39f5c225f2e 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c | |||
| @@ -123,7 +123,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev) | |||
| 123 | return NULL; | 123 | return NULL; |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) { | 126 | for (; dn; dn = of_get_next_parent(dn)) { |
| 127 | ph = of_get_property(dn, "msi-translator", NULL); | 127 | ph = of_get_property(dn, "msi-translator", NULL); |
| 128 | if (ph) | 128 | if (ph) |
| 129 | break; | 129 | break; |
| @@ -169,7 +169,7 @@ static int axon_msi_check_device(struct pci_dev *dev, int nvec, int type) | |||
| 169 | 169 | ||
| 170 | static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg) | 170 | static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg) |
| 171 | { | 171 | { |
| 172 | struct device_node *dn, *tmp; | 172 | struct device_node *dn; |
| 173 | struct msi_desc *entry; | 173 | struct msi_desc *entry; |
| 174 | int len; | 174 | int len; |
| 175 | const u32 *prop; | 175 | const u32 *prop; |
| @@ -182,7 +182,7 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg) | |||
| 182 | 182 | ||
| 183 | entry = list_first_entry(&dev->msi_list, struct msi_desc, list); | 183 | entry = list_first_entry(&dev->msi_list, struct msi_desc, list); |
| 184 | 184 | ||
| 185 | for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) { | 185 | for (; dn; dn = of_get_next_parent(dn)) { |
| 186 | if (entry->msi_attrib.is_64) { | 186 | if (entry->msi_attrib.is_64) { |
| 187 | prop = of_get_property(dn, "msi-address-64", &len); | 187 | prop = of_get_property(dn, "msi-address-64", &len); |
| 188 | if (prop) | 188 | if (prop) |
diff --git a/arch/powerpc/platforms/celleb/beat.c b/arch/powerpc/platforms/cell/beat.c index b64b171f245b..48c690ea65da 100644 --- a/arch/powerpc/platforms/celleb/beat.c +++ b/arch/powerpc/platforms/cell/beat.c | |||
| @@ -33,7 +33,7 @@ | |||
| 33 | 33 | ||
| 34 | #include "beat_wrapper.h" | 34 | #include "beat_wrapper.h" |
| 35 | #include "beat.h" | 35 | #include "beat.h" |
| 36 | #include "interrupt.h" | 36 | #include "beat_interrupt.h" |
| 37 | 37 | ||
| 38 | static int beat_pm_poweroff_flag; | 38 | static int beat_pm_poweroff_flag; |
| 39 | 39 | ||
diff --git a/arch/powerpc/platforms/celleb/beat.h b/arch/powerpc/platforms/cell/beat.h index 32c8efcedc80..32c8efcedc80 100644 --- a/arch/powerpc/platforms/celleb/beat.h +++ b/arch/powerpc/platforms/cell/beat.h | |||
diff --git a/arch/powerpc/platforms/celleb/htab.c b/arch/powerpc/platforms/cell/beat_htab.c index 81467ff055c8..81467ff055c8 100644 --- a/arch/powerpc/platforms/celleb/htab.c +++ b/arch/powerpc/platforms/cell/beat_htab.c | |||
diff --git a/arch/powerpc/platforms/celleb/hvCall.S b/arch/powerpc/platforms/cell/beat_hvCall.S index 74c817448948..74c817448948 100644 --- a/arch/powerpc/platforms/celleb/hvCall.S +++ b/arch/powerpc/platforms/cell/beat_hvCall.S | |||
diff --git a/arch/powerpc/platforms/celleb/interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c index 69562a867876..192a93509372 100644 --- a/arch/powerpc/platforms/celleb/interrupt.c +++ b/arch/powerpc/platforms/cell/beat_interrupt.c | |||
| @@ -26,7 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | #include <asm/machdep.h> | 27 | #include <asm/machdep.h> |
| 28 | 28 | ||
| 29 | #include "interrupt.h" | 29 | #include "beat_interrupt.h" |
| 30 | #include "beat_wrapper.h" | 30 | #include "beat_wrapper.h" |
| 31 | 31 | ||
| 32 | #define MAX_IRQS NR_IRQS | 32 | #define MAX_IRQS NR_IRQS |
diff --git a/arch/powerpc/platforms/celleb/interrupt.h b/arch/powerpc/platforms/cell/beat_interrupt.h index b470fd0051f1..b470fd0051f1 100644 --- a/arch/powerpc/platforms/celleb/interrupt.h +++ b/arch/powerpc/platforms/cell/beat_interrupt.h | |||
diff --git a/arch/powerpc/platforms/celleb/iommu.c b/arch/powerpc/platforms/cell/beat_iommu.c index 93b0efddd658..93b0efddd658 100644 --- a/arch/powerpc/platforms/celleb/iommu.c +++ b/arch/powerpc/platforms/cell/beat_iommu.c | |||
diff --git a/arch/powerpc/platforms/celleb/smp.c b/arch/powerpc/platforms/cell/beat_smp.c index a7631250aeb4..26efc204c47f 100644 --- a/arch/powerpc/platforms/celleb/smp.c +++ b/arch/powerpc/platforms/cell/beat_smp.c | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | #include <asm/machdep.h> | 37 | #include <asm/machdep.h> |
| 38 | #include <asm/udbg.h> | 38 | #include <asm/udbg.h> |
| 39 | 39 | ||
| 40 | #include "interrupt.h" | 40 | #include "beat_interrupt.h" |
| 41 | 41 | ||
| 42 | #ifdef DEBUG | 42 | #ifdef DEBUG |
| 43 | #define DBG(fmt...) udbg_printf(fmt) | 43 | #define DBG(fmt...) udbg_printf(fmt) |
diff --git a/arch/powerpc/platforms/celleb/spu_priv1.c b/arch/powerpc/platforms/cell/beat_spu_priv1.c index bcc17f7fe8ad..bcc17f7fe8ad 100644 --- a/arch/powerpc/platforms/celleb/spu_priv1.c +++ b/arch/powerpc/platforms/cell/beat_spu_priv1.c | |||
diff --git a/arch/powerpc/platforms/celleb/beat_syscall.h b/arch/powerpc/platforms/cell/beat_syscall.h index 8580dc7e1798..8580dc7e1798 100644 --- a/arch/powerpc/platforms/celleb/beat_syscall.h +++ b/arch/powerpc/platforms/cell/beat_syscall.h | |||
diff --git a/arch/powerpc/platforms/celleb/udbg_beat.c b/arch/powerpc/platforms/cell/beat_udbg.c index 6b418f6b6175..6b418f6b6175 100644 --- a/arch/powerpc/platforms/celleb/udbg_beat.c +++ b/arch/powerpc/platforms/cell/beat_udbg.c | |||
diff --git a/arch/powerpc/platforms/celleb/beat_wrapper.h b/arch/powerpc/platforms/cell/beat_wrapper.h index b47dfda48d06..b47dfda48d06 100644 --- a/arch/powerpc/platforms/celleb/beat_wrapper.h +++ b/arch/powerpc/platforms/cell/beat_wrapper.h | |||
diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/cell/celleb_pci.c index 51b390d34e4d..f39a3b2a1667 100644 --- a/arch/powerpc/platforms/celleb/pci.c +++ b/arch/powerpc/platforms/cell/celleb_pci.c | |||
| @@ -37,12 +37,11 @@ | |||
| 37 | #include <asm/io.h> | 37 | #include <asm/io.h> |
| 38 | #include <asm/irq.h> | 38 | #include <asm/irq.h> |
| 39 | #include <asm/prom.h> | 39 | #include <asm/prom.h> |
| 40 | #include <asm/machdep.h> | ||
| 41 | #include <asm/pci-bridge.h> | 40 | #include <asm/pci-bridge.h> |
| 42 | #include <asm/ppc-pci.h> | 41 | #include <asm/ppc-pci.h> |
| 43 | 42 | ||
| 44 | #include "pci.h" | 43 | #include "io-workarounds.h" |
| 45 | #include "interrupt.h" | 44 | #include "celleb_pci.h" |
| 46 | 45 | ||
| 47 | #define MAX_PCI_DEVICES 32 | 46 | #define MAX_PCI_DEVICES 32 |
| 48 | #define MAX_PCI_FUNCTIONS 8 | 47 | #define MAX_PCI_FUNCTIONS 8 |
| @@ -190,7 +189,7 @@ static int celleb_fake_pci_read_config(struct pci_bus *bus, | |||
| 190 | 189 | ||
| 191 | 190 | ||
| 192 | static int celleb_fake_pci_write_config(struct pci_bus *bus, | 191 | static int celleb_fake_pci_write_config(struct pci_bus *bus, |
| 193 | unsigned int devfn, int where, int size, u32 val) | 192 | unsigned int devfn, int where, int size, u32 val) |
| 194 | { | 193 | { |
| 195 | char *config; | 194 | char *config; |
| 196 | struct device_node *node; | 195 | struct device_node *node; |
| @@ -457,33 +456,42 @@ static int __init celleb_setup_fake_pci(struct device_node *dev, | |||
| 457 | return 0; | 456 | return 0; |
| 458 | } | 457 | } |
| 459 | 458 | ||
| 460 | void __init fake_pci_workaround_init(struct pci_controller *phb) | 459 | static struct celleb_phb_spec celleb_fake_pci_spec __initdata = { |
| 461 | { | 460 | .setup = celleb_setup_fake_pci, |
| 462 | /** | 461 | }; |
| 463 | * We will add fake pci bus to scc_pci_bus for the purpose to improve | ||
| 464 | * I/O Macro performance. But device-tree and device drivers | ||
| 465 | * are not ready to use address with a token. | ||
| 466 | */ | ||
| 467 | |||
| 468 | /* celleb_pci_add_one(phb, NULL); */ | ||
| 469 | } | ||
| 470 | 462 | ||
| 471 | static struct of_device_id celleb_phb_match[] __initdata = { | 463 | static struct of_device_id celleb_phb_match[] __initdata = { |
| 472 | { | 464 | { |
| 473 | .name = "pci-pseudo", | 465 | .name = "pci-pseudo", |
| 474 | .data = celleb_setup_fake_pci, | 466 | .data = &celleb_fake_pci_spec, |
| 475 | }, { | 467 | }, { |
| 476 | .name = "epci", | 468 | .name = "epci", |
| 477 | .data = celleb_setup_epci, | 469 | .data = &celleb_epci_spec, |
| 470 | }, { | ||
| 471 | .name = "pcie", | ||
| 472 | .data = &celleb_pciex_spec, | ||
| 478 | }, { | 473 | }, { |
| 479 | }, | 474 | }, |
| 480 | }; | 475 | }; |
| 481 | 476 | ||
| 477 | static int __init celleb_io_workaround_init(struct pci_controller *phb, | ||
| 478 | struct celleb_phb_spec *phb_spec) | ||
| 479 | { | ||
| 480 | if (phb_spec->ops) { | ||
| 481 | iowa_register_bus(phb, phb_spec->ops, phb_spec->iowa_init, | ||
| 482 | phb_spec->iowa_data); | ||
| 483 | io_workaround_init(); | ||
| 484 | } | ||
| 485 | |||
| 486 | return 0; | ||
| 487 | } | ||
| 488 | |||
| 482 | int __init celleb_setup_phb(struct pci_controller *phb) | 489 | int __init celleb_setup_phb(struct pci_controller *phb) |
| 483 | { | 490 | { |
| 484 | struct device_node *dev = phb->dn; | 491 | struct device_node *dev = phb->dn; |
| 485 | const struct of_device_id *match; | 492 | const struct of_device_id *match; |
| 486 | int (*setup_func)(struct device_node *, struct pci_controller *); | 493 | struct celleb_phb_spec *phb_spec; |
| 494 | int rc; | ||
| 487 | 495 | ||
| 488 | match = of_match_node(celleb_phb_match, dev); | 496 | match = of_match_node(celleb_phb_match, dev); |
| 489 | if (!match) | 497 | if (!match) |
| @@ -492,8 +500,12 @@ int __init celleb_setup_phb(struct pci_controller *phb) | |||
| 492 | phb_set_bus_ranges(dev, phb); | 500 | phb_set_bus_ranges(dev, phb); |
| 493 | phb->buid = 1; | 501 | phb->buid = 1; |
| 494 | 502 | ||
| 495 | setup_func = match->data; | 503 | phb_spec = match->data; |
| 496 | return (*setup_func)(dev, phb); | 504 | rc = (*phb_spec->setup)(dev, phb); |
| 505 | if (rc) | ||
| 506 | return 1; | ||
| 507 | |||
| 508 | return celleb_io_workaround_init(phb, phb_spec); | ||
| 497 | } | 509 | } |
| 498 | 510 | ||
| 499 | int celleb_pci_probe_mode(struct pci_bus *bus) | 511 | int celleb_pci_probe_mode(struct pci_bus *bus) |
diff --git a/arch/powerpc/platforms/celleb/pci.h b/arch/powerpc/platforms/cell/celleb_pci.h index 5d5544ffeddb..4cba1523ec50 100644 --- a/arch/powerpc/platforms/celleb/pci.h +++ b/arch/powerpc/platforms/cell/celleb_pci.h | |||
| @@ -27,16 +27,19 @@ | |||
| 27 | #include <asm/prom.h> | 27 | #include <asm/prom.h> |
| 28 | #include <asm/ppc-pci.h> | 28 | #include <asm/ppc-pci.h> |
| 29 | 29 | ||
| 30 | #include "io-workarounds.h" | ||
| 31 | |||
| 32 | struct celleb_phb_spec { | ||
| 33 | int (*setup)(struct device_node *, struct pci_controller *); | ||
| 34 | struct ppc_pci_io *ops; | ||
| 35 | int (*iowa_init)(struct iowa_bus *, void *); | ||
| 36 | void *iowa_data; | ||
| 37 | }; | ||
| 38 | |||
| 30 | extern int celleb_setup_phb(struct pci_controller *); | 39 | extern int celleb_setup_phb(struct pci_controller *); |
| 31 | extern int celleb_pci_probe_mode(struct pci_bus *); | 40 | extern int celleb_pci_probe_mode(struct pci_bus *); |
| 32 | 41 | ||
| 33 | extern int celleb_setup_epci(struct device_node *, struct pci_controller *); | 42 | extern struct celleb_phb_spec celleb_epci_spec; |
| 34 | 43 | extern struct celleb_phb_spec celleb_pciex_spec; | |
| 35 | extern void *celleb_dummy_page_va; | ||
| 36 | extern int __init celleb_pci_workaround_init(void); | ||
| 37 | extern void __init celleb_pci_add_one(struct pci_controller *, | ||
| 38 | void (*)(struct pci_controller *)); | ||
| 39 | extern void fake_pci_workaround_init(struct pci_controller *); | ||
| 40 | extern void epci_workaround_init(struct pci_controller *); | ||
| 41 | 44 | ||
| 42 | #endif /* _CELLEB_PCI_H */ | 45 | #endif /* _CELLEB_PCI_H */ |
diff --git a/arch/powerpc/platforms/celleb/scc.h b/arch/powerpc/platforms/cell/celleb_scc.h index 6be1542a6e66..b596a711c348 100644 --- a/arch/powerpc/platforms/celleb/scc.h +++ b/arch/powerpc/platforms/cell/celleb_scc.h | |||
| @@ -125,6 +125,93 @@ | |||
| 125 | /* bits for SCC_EPCI_CNTOPT */ | 125 | /* bits for SCC_EPCI_CNTOPT */ |
| 126 | #define SCC_EPCI_CNTOPT_O2PMB 0x00000002 | 126 | #define SCC_EPCI_CNTOPT_O2PMB 0x00000002 |
| 127 | 127 | ||
| 128 | /* SCC PCIEXC SMMIO registers */ | ||
| 129 | #define PEXCADRS 0x000 | ||
| 130 | #define PEXCWDATA 0x004 | ||
| 131 | #define PEXCRDATA 0x008 | ||
| 132 | #define PEXDADRS 0x010 | ||
| 133 | #define PEXDCMND 0x014 | ||
| 134 | #define PEXDWDATA 0x018 | ||
| 135 | #define PEXDRDATA 0x01c | ||
| 136 | #define PEXREQID 0x020 | ||
| 137 | #define PEXTIDMAP 0x024 | ||
| 138 | #define PEXINTMASK 0x028 | ||
| 139 | #define PEXINTSTS 0x02c | ||
| 140 | #define PEXAERRMASK 0x030 | ||
| 141 | #define PEXAERRSTS 0x034 | ||
| 142 | #define PEXPRERRMASK 0x040 | ||
| 143 | #define PEXPRERRSTS 0x044 | ||
| 144 | #define PEXPRERRID01 0x048 | ||
| 145 | #define PEXPRERRID23 0x04c | ||
| 146 | #define PEXVDMASK 0x050 | ||
| 147 | #define PEXVDSTS 0x054 | ||
| 148 | #define PEXRCVCPLIDA 0x060 | ||
| 149 | #define PEXLENERRIDA 0x068 | ||
| 150 | #define PEXPHYPLLST 0x070 | ||
| 151 | #define PEXDMRDEN0 0x100 | ||
| 152 | #define PEXDMRDADR0 0x104 | ||
| 153 | #define PEXDMRDENX 0x110 | ||
| 154 | #define PEXDMRDADRX 0x114 | ||
| 155 | #define PEXECMODE 0xf00 | ||
| 156 | #define PEXMAEA(n) (0xf50 + (8 * n)) | ||
| 157 | #define PEXMAEC(n) (0xf54 + (8 * n)) | ||
| 158 | #define PEXCCRCTRL 0xff0 | ||
| 159 | |||
| 160 | /* SCC PCIEXC bits and shifts for PEXCADRS */ | ||
| 161 | #define PEXCADRS_BYTE_EN_SHIFT 20 | ||
| 162 | #define PEXCADRS_CMD_SHIFT 16 | ||
| 163 | #define PEXCADRS_CMD_READ (0xa << PEXCADRS_CMD_SHIFT) | ||
| 164 | #define PEXCADRS_CMD_WRITE (0xb << PEXCADRS_CMD_SHIFT) | ||
| 165 | |||
| 166 | /* SCC PCIEXC shifts for PEXDADRS */ | ||
| 167 | #define PEXDADRS_BUSNO_SHIFT 20 | ||
| 168 | #define PEXDADRS_DEVNO_SHIFT 15 | ||
| 169 | #define PEXDADRS_FUNCNO_SHIFT 12 | ||
| 170 | |||
| 171 | /* SCC PCIEXC bits and shifts for PEXDCMND */ | ||
| 172 | #define PEXDCMND_BYTE_EN_SHIFT 4 | ||
| 173 | #define PEXDCMND_IO_READ 0x2 | ||
| 174 | #define PEXDCMND_IO_WRITE 0x3 | ||
| 175 | #define PEXDCMND_CONFIG_READ 0xa | ||
| 176 | #define PEXDCMND_CONFIG_WRITE 0xb | ||
| 177 | |||
| 178 | /* SCC PCIEXC bits for PEXPHYPLLST */ | ||
| 179 | #define PEXPHYPLLST_PEXPHYAPLLST 0x00000001 | ||
| 180 | |||
| 181 | /* SCC PCIEXC bits for PEXECMODE */ | ||
| 182 | #define PEXECMODE_ALL_THROUGH 0x00000000 | ||
| 183 | #define PEXECMODE_ALL_8BIT 0x00550155 | ||
| 184 | #define PEXECMODE_ALL_16BIT 0x00aa02aa | ||
| 185 | |||
| 186 | /* SCC PCIEXC bits for PEXCCRCTRL */ | ||
| 187 | #define PEXCCRCTRL_PEXIPCOREEN 0x00040000 | ||
| 188 | #define PEXCCRCTRL_PEXIPCONTEN 0x00020000 | ||
| 189 | #define PEXCCRCTRL_PEXPHYPLLEN 0x00010000 | ||
| 190 | #define PEXCCRCTRL_PCIEXCAOCKEN 0x00000100 | ||
| 191 | |||
| 192 | /* SCC PCIEXC port configuration registers */ | ||
| 193 | #define PEXTCERRCHK 0x21c | ||
| 194 | #define PEXTAMAPB0 0x220 | ||
| 195 | #define PEXTAMAPL0 0x224 | ||
| 196 | #define PEXTAMAPB(n) (PEXTAMAPB0 + 8 * (n)) | ||
| 197 | #define PEXTAMAPL(n) (PEXTAMAPL0 + 8 * (n)) | ||
| 198 | #define PEXCHVC0P 0x500 | ||
| 199 | #define PEXCHVC0NP 0x504 | ||
| 200 | #define PEXCHVC0C 0x508 | ||
| 201 | #define PEXCDVC0P 0x50c | ||
| 202 | #define PEXCDVC0NP 0x510 | ||
| 203 | #define PEXCDVC0C 0x514 | ||
| 204 | #define PEXCHVCXP 0x518 | ||
| 205 | #define PEXCHVCXNP 0x51c | ||
| 206 | #define PEXCHVCXC 0x520 | ||
| 207 | #define PEXCDVCXP 0x524 | ||
| 208 | #define PEXCDVCXNP 0x528 | ||
| 209 | #define PEXCDVCXC 0x52c | ||
| 210 | #define PEXCTTRG 0x530 | ||
| 211 | #define PEXTSCTRL 0x700 | ||
| 212 | #define PEXTSSTS 0x704 | ||
| 213 | #define PEXSKPCTRL 0x708 | ||
| 214 | |||
| 128 | /* UHC registers */ | 215 | /* UHC registers */ |
| 129 | #define SCC_UHC_CKRCTRL 0xff0 | 216 | #define SCC_UHC_CKRCTRL 0xff0 |
| 130 | #define SCC_UHC_ECMODE 0xf00 | 217 | #define SCC_UHC_ECMODE 0xf00 |
diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/cell/celleb_scc_epci.c index a999b393f6f6..08c285b10e30 100644 --- a/arch/powerpc/platforms/celleb/scc_epci.c +++ b/arch/powerpc/platforms/cell/celleb_scc_epci.c | |||
| @@ -30,23 +30,17 @@ | |||
| 30 | #include <asm/io.h> | 30 | #include <asm/io.h> |
| 31 | #include <asm/irq.h> | 31 | #include <asm/irq.h> |
| 32 | #include <asm/prom.h> | 32 | #include <asm/prom.h> |
| 33 | #include <asm/machdep.h> | ||
| 34 | #include <asm/pci-bridge.h> | 33 | #include <asm/pci-bridge.h> |
| 35 | #include <asm/ppc-pci.h> | 34 | #include <asm/ppc-pci.h> |
| 36 | 35 | ||
| 37 | #include "scc.h" | 36 | #include "celleb_scc.h" |
| 38 | #include "pci.h" | 37 | #include "celleb_pci.h" |
| 39 | #include "interrupt.h" | ||
| 40 | 38 | ||
| 41 | #define MAX_PCI_DEVICES 32 | 39 | #define MAX_PCI_DEVICES 32 |
| 42 | #define MAX_PCI_FUNCTIONS 8 | 40 | #define MAX_PCI_FUNCTIONS 8 |
| 43 | 41 | ||
| 44 | #define iob() __asm__ __volatile__("eieio; sync":::"memory") | 42 | #define iob() __asm__ __volatile__("eieio; sync":::"memory") |
| 45 | 43 | ||
| 46 | struct epci_private { | ||
| 47 | dma_addr_t dummy_page_da; | ||
| 48 | }; | ||
| 49 | |||
| 50 | static inline PCI_IO_ADDR celleb_epci_get_epci_base( | 44 | static inline PCI_IO_ADDR celleb_epci_get_epci_base( |
| 51 | struct pci_controller *hose) | 45 | struct pci_controller *hose) |
| 52 | { | 46 | { |
| @@ -71,42 +65,6 @@ static inline PCI_IO_ADDR celleb_epci_get_epci_cfg( | |||
| 71 | return hose->cfg_data; | 65 | return hose->cfg_data; |
| 72 | } | 66 | } |
| 73 | 67 | ||
| 74 | static void scc_epci_dummy_read(struct pci_controller *hose) | ||
| 75 | { | ||
| 76 | PCI_IO_ADDR epci_base; | ||
| 77 | u32 val; | ||
| 78 | |||
| 79 | epci_base = celleb_epci_get_epci_base(hose); | ||
| 80 | |||
| 81 | val = in_be32(epci_base + SCC_EPCI_WATRP); | ||
| 82 | iosync(); | ||
| 83 | |||
| 84 | return; | ||
| 85 | } | ||
| 86 | |||
| 87 | void __init epci_workaround_init(struct pci_controller *hose) | ||
| 88 | { | ||
| 89 | PCI_IO_ADDR epci_base; | ||
| 90 | PCI_IO_ADDR reg; | ||
| 91 | struct epci_private *private = hose->private_data; | ||
| 92 | |||
| 93 | BUG_ON(!private); | ||
| 94 | |||
| 95 | private->dummy_page_da = dma_map_single(hose->parent, | ||
| 96 | celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE); | ||
| 97 | if (private->dummy_page_da == DMA_ERROR_CODE) { | ||
| 98 | printk(KERN_ERR "EPCI: dummy read disabled. " | ||
| 99 | "Map dummy page failed.\n"); | ||
| 100 | return; | ||
| 101 | } | ||
| 102 | |||
| 103 | celleb_pci_add_one(hose, scc_epci_dummy_read); | ||
| 104 | epci_base = celleb_epci_get_epci_base(hose); | ||
| 105 | |||
| 106 | reg = epci_base + SCC_EPCI_DUMYRADR; | ||
| 107 | out_be32(reg, private->dummy_page_da); | ||
| 108 | } | ||
| 109 | |||
| 110 | static inline void clear_and_disable_master_abort_interrupt( | 68 | static inline void clear_and_disable_master_abort_interrupt( |
| 111 | struct pci_controller *hose) | 69 | struct pci_controller *hose) |
| 112 | { | 70 | { |
| @@ -151,10 +109,8 @@ static int celleb_epci_check_abort(struct pci_controller *hose, | |||
| 151 | return PCIBIOS_SUCCESSFUL; | 109 | return PCIBIOS_SUCCESSFUL; |
| 152 | } | 110 | } |
| 153 | 111 | ||
| 154 | static PCI_IO_ADDR celleb_epci_make_config_addr( | 112 | static PCI_IO_ADDR celleb_epci_make_config_addr(struct pci_bus *bus, |
| 155 | struct pci_bus *bus, | 113 | struct pci_controller *hose, unsigned int devfn, int where) |
| 156 | struct pci_controller *hose, | ||
| 157 | unsigned int devfn, int where) | ||
| 158 | { | 114 | { |
| 159 | PCI_IO_ADDR addr; | 115 | PCI_IO_ADDR addr; |
| 160 | 116 | ||
| @@ -425,8 +381,8 @@ static int __init celleb_epci_init(struct pci_controller *hose) | |||
| 425 | return 0; | 381 | return 0; |
| 426 | } | 382 | } |
| 427 | 383 | ||
| 428 | int __init celleb_setup_epci(struct device_node *node, | 384 | static int __init celleb_setup_epci(struct device_node *node, |
| 429 | struct pci_controller *hose) | 385 | struct pci_controller *hose) |
| 430 | { | 386 | { |
| 431 | struct resource r; | 387 | struct resource r; |
| 432 | 388 | ||
| @@ -450,8 +406,7 @@ int __init celleb_setup_epci(struct device_node *node, | |||
| 450 | if (!hose->cfg_addr) | 406 | if (!hose->cfg_addr) |
| 451 | goto error; | 407 | goto error; |
| 452 | pr_debug("EPCI: cfg_addr map 0x%016lx->0x%016lx + 0x%016lx\n", | 408 | pr_debug("EPCI: cfg_addr map 0x%016lx->0x%016lx + 0x%016lx\n", |
| 453 | r.start, (unsigned long)hose->cfg_addr, | 409 | r.start, (unsigned long)hose->cfg_addr, (r.end - r.start + 1)); |
| 454 | (r.end - r.start + 1)); | ||
| 455 | 410 | ||
| 456 | if (of_address_to_resource(node, 2, &r)) | 411 | if (of_address_to_resource(node, 2, &r)) |
| 457 | goto error; | 412 | goto error; |
| @@ -459,14 +414,7 @@ int __init celleb_setup_epci(struct device_node *node, | |||
| 459 | if (!hose->cfg_data) | 414 | if (!hose->cfg_data) |
| 460 | goto error; | 415 | goto error; |
| 461 | pr_debug("EPCI: cfg_data map 0x%016lx->0x%016lx + 0x%016lx\n", | 416 | pr_debug("EPCI: cfg_data map 0x%016lx->0x%016lx + 0x%016lx\n", |
| 462 | r.start, (unsigned long)hose->cfg_data, | 417 | r.start, (unsigned long)hose->cfg_data, (r.end - r.start + 1)); |
| 463 | (r.end - r.start + 1)); | ||
| 464 | |||
| 465 | hose->private_data = kzalloc(sizeof(struct epci_private), GFP_KERNEL); | ||
| 466 | if (hose->private_data == NULL) { | ||
| 467 | printk(KERN_ERR "EPCI: no memory for private data.\n"); | ||
| 468 | goto error; | ||
| 469 | } | ||
| 470 | 418 | ||
| 471 | hose->ops = &celleb_epci_ops; | 419 | hose->ops = &celleb_epci_ops; |
| 472 | celleb_epci_init(hose); | 420 | celleb_epci_init(hose); |
| @@ -474,8 +422,6 @@ int __init celleb_setup_epci(struct device_node *node, | |||
| 474 | return 0; | 422 | return 0; |
| 475 | 423 | ||
| 476 | error: | 424 | error: |
| 477 | kfree(hose->private_data); | ||
| 478 | |||
| 479 | if (hose->cfg_addr) | 425 | if (hose->cfg_addr) |
| 480 | iounmap(hose->cfg_addr); | 426 | iounmap(hose->cfg_addr); |
| 481 | 427 | ||
| @@ -483,3 +429,10 @@ error: | |||
| 483 | iounmap(hose->cfg_data); | 429 | iounmap(hose->cfg_data); |
| 484 | return 1; | 430 | return 1; |
| 485 | } | 431 | } |
| 432 | |||
| 433 | struct celleb_phb_spec celleb_epci_spec __initdata = { | ||
| 434 | .setup = celleb_setup_epci, | ||
| 435 | .ops = &spiderpci_ops, | ||
| 436 | .iowa_init = &spiderpci_iowa_init, | ||
| 437 | .iowa_data = (void *)0, | ||
| 438 | }; | ||
diff --git a/arch/powerpc/platforms/cell/celleb_scc_pciex.c b/arch/powerpc/platforms/cell/celleb_scc_pciex.c new file mode 100644 index 000000000000..ab24d94baab6 --- /dev/null +++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c | |||
| @@ -0,0 +1,547 @@ | |||
| 1 | /* | ||
| 2 | * Support for Celleb PCI-Express. | ||
| 3 | * | ||
| 4 | * (C) Copyright 2007-2008 TOSHIBA CORPORATION | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #undef DEBUG | ||
| 22 | |||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/pci.h> | ||
| 25 | #include <linux/string.h> | ||
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/bootmem.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | #include <linux/interrupt.h> | ||
| 30 | |||
| 31 | #include <asm/io.h> | ||
| 32 | #include <asm/irq.h> | ||
| 33 | #include <asm/iommu.h> | ||
| 34 | #include <asm/byteorder.h> | ||
| 35 | |||
| 36 | #include "celleb_scc.h" | ||
| 37 | #include "celleb_pci.h" | ||
| 38 | |||
| 39 | #define PEX_IN(base, off) in_be32((void *)(base) + (off)) | ||
| 40 | #define PEX_OUT(base, off, data) out_be32((void *)(base) + (off), (data)) | ||
| 41 | |||
| 42 | static void scc_pciex_io_flush(struct iowa_bus *bus) | ||
| 43 | { | ||
| 44 | (void)PEX_IN(bus->phb->cfg_addr, PEXDMRDEN0); | ||
| 45 | } | ||
| 46 | |||
| 47 | /* | ||
| 48 | * Memory space access to device on PCIEX | ||
| 49 | */ | ||
| 50 | #define PCIEX_MMIO_READ(name, ret) \ | ||
| 51 | static ret scc_pciex_##name(const PCI_IO_ADDR addr) \ | ||
| 52 | { \ | ||
| 53 | ret val = __do_##name(addr); \ | ||
| 54 | scc_pciex_io_flush(iowa_mem_find_bus(addr)); \ | ||
| 55 | return val; \ | ||
| 56 | } | ||
| 57 | |||
| 58 | #define PCIEX_MMIO_READ_STR(name) \ | ||
| 59 | static void scc_pciex_##name(const PCI_IO_ADDR addr, void *buf, \ | ||
| 60 | unsigned long count) \ | ||
| 61 | { \ | ||
| 62 | __do_##name(addr, buf, count); \ | ||
| 63 | scc_pciex_io_flush(iowa_mem_find_bus(addr)); \ | ||
| 64 | } | ||
| 65 | |||
| 66 | PCIEX_MMIO_READ(readb, u8) | ||
| 67 | PCIEX_MMIO_READ(readw, u16) | ||
| 68 | PCIEX_MMIO_READ(readl, u32) | ||
| 69 | PCIEX_MMIO_READ(readq, u64) | ||
| 70 | PCIEX_MMIO_READ(readw_be, u16) | ||
| 71 | PCIEX_MMIO_READ(readl_be, u32) | ||
| 72 | PCIEX_MMIO_READ(readq_be, u64) | ||
| 73 | PCIEX_MMIO_READ_STR(readsb) | ||
| 74 | PCIEX_MMIO_READ_STR(readsw) | ||
| 75 | PCIEX_MMIO_READ_STR(readsl) | ||
| 76 | |||
| 77 | static void scc_pciex_memcpy_fromio(void *dest, const PCI_IO_ADDR src, | ||
| 78 | unsigned long n) | ||
| 79 | { | ||
| 80 | __do_memcpy_fromio(dest, src, n); | ||
| 81 | scc_pciex_io_flush(iowa_mem_find_bus(src)); | ||
| 82 | } | ||
| 83 | |||
| 84 | /* | ||
| 85 | * I/O port access to devices on PCIEX. | ||
| 86 | */ | ||
| 87 | |||
| 88 | static inline unsigned long get_bus_address(struct pci_controller *phb, | ||
| 89 | unsigned long port) | ||
| 90 | { | ||
| 91 | return port - ((unsigned long)(phb->io_base_virt) - _IO_BASE); | ||
| 92 | } | ||
| 93 | |||
| 94 | static u32 scc_pciex_read_port(struct pci_controller *phb, | ||
| 95 | unsigned long port, int size) | ||
| 96 | { | ||
| 97 | unsigned int byte_enable; | ||
| 98 | unsigned int cmd, shift; | ||
| 99 | unsigned long addr; | ||
| 100 | u32 data, ret; | ||
| 101 | |||
| 102 | BUG_ON(((port & 0x3ul) + size) > 4); | ||
| 103 | |||
| 104 | addr = get_bus_address(phb, port); | ||
| 105 | shift = addr & 0x3ul; | ||
| 106 | byte_enable = ((1 << size) - 1) << shift; | ||
| 107 | cmd = PEXDCMND_IO_READ | (byte_enable << PEXDCMND_BYTE_EN_SHIFT); | ||
| 108 | PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul)); | ||
| 109 | PEX_OUT(phb->cfg_addr, PEXDCMND, cmd); | ||
| 110 | data = PEX_IN(phb->cfg_addr, PEXDRDATA); | ||
| 111 | ret = (data >> (shift * 8)) & (0xFFFFFFFF >> ((4 - size) * 8)); | ||
| 112 | |||
| 113 | pr_debug("PCIEX:PIO READ:port=0x%lx, addr=0x%lx, size=%d, be=%x," | ||
| 114 | " cmd=%x, data=%x, ret=%x\n", port, addr, size, byte_enable, | ||
| 115 | cmd, data, ret); | ||
| 116 | |||
| 117 | return ret; | ||
| 118 | } | ||
| 119 | |||
| 120 | static void scc_pciex_write_port(struct pci_controller *phb, | ||
| 121 | unsigned long port, int size, u32 val) | ||
| 122 | { | ||
| 123 | unsigned int byte_enable; | ||
| 124 | unsigned int cmd, shift; | ||
| 125 | unsigned long addr; | ||
| 126 | u32 data; | ||
| 127 | |||
| 128 | BUG_ON(((port & 0x3ul) + size) > 4); | ||
| 129 | |||
| 130 | addr = get_bus_address(phb, port); | ||
| 131 | shift = addr & 0x3ul; | ||
| 132 | byte_enable = ((1 << size) - 1) << shift; | ||
| 133 | cmd = PEXDCMND_IO_WRITE | (byte_enable << PEXDCMND_BYTE_EN_SHIFT); | ||
| 134 | data = (val & (0xFFFFFFFF >> (4 - size) * 8)) << (shift * 8); | ||
| 135 | PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul)); | ||
| 136 | PEX_OUT(phb->cfg_addr, PEXDCMND, cmd); | ||
| 137 | PEX_OUT(phb->cfg_addr, PEXDWDATA, data); | ||
| 138 | |||
| 139 | pr_debug("PCIEX:PIO WRITE:port=0x%lx, addr=%lx, size=%d, val=%x," | ||
| 140 | " be=%x, cmd=%x, data=%x\n", port, addr, size, val, | ||
| 141 | byte_enable, cmd, data); | ||
| 142 | } | ||
| 143 | |||
| 144 | static u8 __scc_pciex_inb(struct pci_controller *phb, unsigned long port) | ||
| 145 | { | ||
| 146 | return (u8)scc_pciex_read_port(phb, port, 1); | ||
| 147 | } | ||
| 148 | |||
| 149 | static u16 __scc_pciex_inw(struct pci_controller *phb, unsigned long port) | ||
| 150 | { | ||
| 151 | u32 data; | ||
| 152 | if ((port & 0x3ul) < 3) | ||
| 153 | data = scc_pciex_read_port(phb, port, 2); | ||
| 154 | else { | ||
| 155 | u32 d1 = scc_pciex_read_port(phb, port, 1); | ||
| 156 | u32 d2 = scc_pciex_read_port(phb, port + 1, 1); | ||
| 157 | data = d1 | (d2 << 8); | ||
| 158 | } | ||
| 159 | return (u16)data; | ||
| 160 | } | ||
| 161 | |||
| 162 | static u32 __scc_pciex_inl(struct pci_controller *phb, unsigned long port) | ||
| 163 | { | ||
| 164 | unsigned int mod = port & 0x3ul; | ||
| 165 | u32 data; | ||
| 166 | if (mod == 0) | ||
| 167 | data = scc_pciex_read_port(phb, port, 4); | ||
| 168 | else { | ||
| 169 | u32 d1 = scc_pciex_read_port(phb, port, 4 - mod); | ||
| 170 | u32 d2 = scc_pciex_read_port(phb, port + 1, mod); | ||
| 171 | data = d1 | (d2 << (mod * 8)); | ||
| 172 | } | ||
| 173 | return data; | ||
| 174 | } | ||
| 175 | |||
| 176 | static void __scc_pciex_outb(struct pci_controller *phb, | ||
| 177 | u8 val, unsigned long port) | ||
| 178 | { | ||
| 179 | scc_pciex_write_port(phb, port, 1, (u32)val); | ||
| 180 | } | ||
| 181 | |||
| 182 | static void __scc_pciex_outw(struct pci_controller *phb, | ||
| 183 | u16 val, unsigned long port) | ||
| 184 | { | ||
| 185 | if ((port & 0x3ul) < 3) | ||
| 186 | scc_pciex_write_port(phb, port, 2, (u32)val); | ||
| 187 | else { | ||
| 188 | u32 d1 = val & 0x000000FF; | ||
| 189 | u32 d2 = (val & 0x0000FF00) >> 8; | ||
| 190 | scc_pciex_write_port(phb, port, 1, d1); | ||
| 191 | scc_pciex_write_port(phb, port + 1, 1, d2); | ||
| 192 | } | ||
| 193 | } | ||
| 194 | |||
| 195 | static void __scc_pciex_outl(struct pci_controller *phb, | ||
| 196 | u32 val, unsigned long port) | ||
| 197 | { | ||
| 198 | unsigned int mod = port & 0x3ul; | ||
| 199 | if (mod == 0) | ||
| 200 | scc_pciex_write_port(phb, port, 4, val); | ||
| 201 | else { | ||
| 202 | u32 d1 = val & (0xFFFFFFFFul >> (mod * 8)); | ||
| 203 | u32 d2 = val >> ((4 - mod) * 8); | ||
| 204 | scc_pciex_write_port(phb, port, 4 - mod, d1); | ||
| 205 | scc_pciex_write_port(phb, port + 1, mod, d2); | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | #define PCIEX_PIO_FUNC(size, name) \ | ||
| 210 | static u##size scc_pciex_in##name(unsigned long port) \ | ||
| 211 | { \ | ||
| 212 | struct iowa_bus *bus = iowa_pio_find_bus(port); \ | ||
| 213 | u##size data = __scc_pciex_in##name(bus->phb, port); \ | ||
| 214 | scc_pciex_io_flush(bus); \ | ||
| 215 | return data; \ | ||
| 216 | } \ | ||
| 217 | static void scc_pciex_ins##name(unsigned long p, void *b, unsigned long c) \ | ||
| 218 | { \ | ||
| 219 | struct iowa_bus *bus = iowa_pio_find_bus(p); \ | ||
| 220 | u##size *dst = b; \ | ||
| 221 | for (; c != 0; c--, dst++) \ | ||
| 222 | *dst = cpu_to_le##size(__scc_pciex_in##name(bus->phb, p)); \ | ||
| 223 | scc_pciex_io_flush(bus); \ | ||
| 224 | } \ | ||
| 225 | static void scc_pciex_out##name(u##size val, unsigned long port) \ | ||
| 226 | { \ | ||
| 227 | struct iowa_bus *bus = iowa_pio_find_bus(port); \ | ||
| 228 | __scc_pciex_out##name(bus->phb, val, port); \ | ||
| 229 | } \ | ||
| 230 | static void scc_pciex_outs##name(unsigned long p, const void *b, \ | ||
| 231 | unsigned long c) \ | ||
| 232 | { \ | ||
| 233 | struct iowa_bus *bus = iowa_pio_find_bus(p); \ | ||
| 234 | const u##size *src = b; \ | ||
| 235 | for (; c != 0; c--, src++) \ | ||
| 236 | __scc_pciex_out##name(bus->phb, le##size##_to_cpu(*src), p); \ | ||
| 237 | } | ||
| 238 | #define cpu_to_le8(x) (x) | ||
| 239 | #define le8_to_cpu(x) (x) | ||
| 240 | PCIEX_PIO_FUNC(8, b) | ||
| 241 | PCIEX_PIO_FUNC(16, w) | ||
| 242 | PCIEX_PIO_FUNC(32, l) | ||
| 243 | |||
| 244 | static struct ppc_pci_io scc_pciex_ops = { | ||
| 245 | .readb = scc_pciex_readb, | ||
| 246 | .readw = scc_pciex_readw, | ||
| 247 | .readl = scc_pciex_readl, | ||
| 248 | .readq = scc_pciex_readq, | ||
| 249 | .readw_be = scc_pciex_readw_be, | ||
| 250 | .readl_be = scc_pciex_readl_be, | ||
| 251 | .readq_be = scc_pciex_readq_be, | ||
| 252 | .readsb = scc_pciex_readsb, | ||
| 253 | .readsw = scc_pciex_readsw, | ||
| 254 | .readsl = scc_pciex_readsl, | ||
| 255 | .memcpy_fromio = scc_pciex_memcpy_fromio, | ||
| 256 | .inb = scc_pciex_inb, | ||
| 257 | .inw = scc_pciex_inw, | ||
| 258 | .inl = scc_pciex_inl, | ||
| 259 | .outb = scc_pciex_outb, | ||
| 260 | .outw = scc_pciex_outw, | ||
| 261 | .outl = scc_pciex_outl, | ||
| 262 | .insb = scc_pciex_insb, | ||
| 263 | .insw = scc_pciex_insw, | ||
| 264 | .insl = scc_pciex_insl, | ||
| 265 | .outsb = scc_pciex_outsb, | ||
| 266 | .outsw = scc_pciex_outsw, | ||
| 267 | .outsl = scc_pciex_outsl, | ||
| 268 | }; | ||
| 269 | |||
| 270 | static int __init scc_pciex_iowa_init(struct iowa_bus *bus, void *data) | ||
| 271 | { | ||
| 272 | dma_addr_t dummy_page_da; | ||
| 273 | void *dummy_page_va; | ||
| 274 | |||
| 275 | dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 276 | if (!dummy_page_va) { | ||
| 277 | pr_err("PCIEX:Alloc dummy_page_va failed\n"); | ||
| 278 | return -1; | ||
| 279 | } | ||
| 280 | |||
| 281 | dummy_page_da = dma_map_single(bus->phb->parent, dummy_page_va, | ||
| 282 | PAGE_SIZE, DMA_FROM_DEVICE); | ||
| 283 | if (dma_mapping_error(dummy_page_da)) { | ||
| 284 | pr_err("PCIEX:Map dummy page failed.\n"); | ||
| 285 | kfree(dummy_page_va); | ||
| 286 | return -1; | ||
| 287 | } | ||
| 288 | |||
| 289 | PEX_OUT(bus->phb->cfg_addr, PEXDMRDADR0, dummy_page_da); | ||
| 290 | |||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | /* | ||
| 295 | * config space access | ||
| 296 | */ | ||
| 297 | #define MK_PEXDADRS(bus_no, dev_no, func_no, addr) \ | ||
| 298 | ((uint32_t)(((addr) & ~0x3UL) | \ | ||
| 299 | ((bus_no) << PEXDADRS_BUSNO_SHIFT) | \ | ||
| 300 | ((dev_no) << PEXDADRS_DEVNO_SHIFT) | \ | ||
| 301 | ((func_no) << PEXDADRS_FUNCNO_SHIFT))) | ||
| 302 | |||
| 303 | #define MK_PEXDCMND_BYTE_EN(addr, size) \ | ||
| 304 | ((((0x1 << (size))-1) << ((addr) & 0x3)) << PEXDCMND_BYTE_EN_SHIFT) | ||
| 305 | #define MK_PEXDCMND(cmd, addr, size) ((cmd) | MK_PEXDCMND_BYTE_EN(addr, size)) | ||
| 306 | |||
| 307 | static uint32_t config_read_pciex_dev(unsigned int *base, | ||
| 308 | uint64_t bus_no, uint64_t dev_no, uint64_t func_no, | ||
| 309 | uint64_t off, uint64_t size) | ||
| 310 | { | ||
| 311 | uint32_t ret; | ||
| 312 | uint32_t addr, cmd; | ||
| 313 | |||
| 314 | addr = MK_PEXDADRS(bus_no, dev_no, func_no, off); | ||
| 315 | cmd = MK_PEXDCMND(PEXDCMND_CONFIG_READ, off, size); | ||
| 316 | PEX_OUT(base, PEXDADRS, addr); | ||
| 317 | PEX_OUT(base, PEXDCMND, cmd); | ||
| 318 | ret = (PEX_IN(base, PEXDRDATA) | ||
| 319 | >> ((off & (4-size)) * 8)) & ((0x1 << (size * 8)) - 1); | ||
| 320 | return ret; | ||
| 321 | } | ||
| 322 | |||
| 323 | static void config_write_pciex_dev(unsigned int *base, uint64_t bus_no, | ||
| 324 | uint64_t dev_no, uint64_t func_no, uint64_t off, uint64_t size, | ||
| 325 | uint32_t data) | ||
| 326 | { | ||
| 327 | uint32_t addr, cmd; | ||
| 328 | |||
| 329 | addr = MK_PEXDADRS(bus_no, dev_no, func_no, off); | ||
| 330 | cmd = MK_PEXDCMND(PEXDCMND_CONFIG_WRITE, off, size); | ||
| 331 | PEX_OUT(base, PEXDADRS, addr); | ||
| 332 | PEX_OUT(base, PEXDCMND, cmd); | ||
| 333 | PEX_OUT(base, PEXDWDATA, | ||
| 334 | (data & ((0x1 << (size * 8)) - 1)) << ((off & (4-size)) * 8)); | ||
| 335 | } | ||
| 336 | |||
| 337 | #define MK_PEXCADRS_BYTE_EN(off, len) \ | ||
| 338 | ((((0x1 << (len)) - 1) << ((off) & 0x3)) << PEXCADRS_BYTE_EN_SHIFT) | ||
| 339 | #define MK_PEXCADRS(cmd, addr, size) \ | ||
| 340 | ((cmd) | MK_PEXCADRS_BYTE_EN(addr, size) | ((addr) & ~0x3)) | ||
| 341 | static uint32_t config_read_pciex_rc(unsigned int *base, | ||
| 342 | uint32_t where, uint32_t size) | ||
| 343 | { | ||
| 344 | PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_READ, where, size)); | ||
| 345 | return (PEX_IN(base, PEXCRDATA) | ||
| 346 | >> ((where & (4 - size)) * 8)) & ((0x1 << (size * 8)) - 1); | ||
| 347 | } | ||
| 348 | |||
| 349 | static void config_write_pciex_rc(unsigned int *base, uint32_t where, | ||
| 350 | uint32_t size, uint32_t val) | ||
| 351 | { | ||
| 352 | uint32_t data; | ||
| 353 | |||
| 354 | data = (val & ((0x1 << (size * 8)) - 1)) << ((where & (4 - size)) * 8); | ||
| 355 | PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_WRITE, where, size)); | ||
| 356 | PEX_OUT(base, PEXCWDATA, data); | ||
| 357 | } | ||
| 358 | |||
| 359 | /* Interfaces */ | ||
| 360 | /* Note: Work-around | ||
| 361 | * On SCC PCIEXC, one device is seen on all 32 dev_no. | ||
| 362 | * As SCC PCIEXC can have only one device on the bus, we look only one dev_no. | ||
| 363 | * (dev_no = 1) | ||
| 364 | */ | ||
| 365 | static int scc_pciex_read_config(struct pci_bus *bus, unsigned int devfn, | ||
| 366 | int where, int size, unsigned int *val) | ||
| 367 | { | ||
| 368 | struct device_node *dn; | ||
| 369 | struct pci_controller *phb; | ||
| 370 | |||
| 371 | dn = bus->sysdata; | ||
| 372 | phb = pci_find_hose_for_OF_device(dn); | ||
| 373 | |||
| 374 | if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1) { | ||
| 375 | *val = ~0; | ||
| 376 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 377 | } | ||
| 378 | |||
| 379 | if (bus->number == 0 && PCI_SLOT(devfn) == 0) | ||
| 380 | *val = config_read_pciex_rc(phb->cfg_addr, where, size); | ||
| 381 | else | ||
| 382 | *val = config_read_pciex_dev(phb->cfg_addr, bus->number, | ||
| 383 | PCI_SLOT(devfn), PCI_FUNC(devfn), where, size); | ||
| 384 | |||
| 385 | return PCIBIOS_SUCCESSFUL; | ||
| 386 | } | ||
| 387 | |||
| 388 | static int scc_pciex_write_config(struct pci_bus *bus, unsigned int devfn, | ||
| 389 | int where, int size, unsigned int val) | ||
| 390 | { | ||
| 391 | struct device_node *dn; | ||
| 392 | struct pci_controller *phb; | ||
| 393 | |||
| 394 | dn = bus->sysdata; | ||
| 395 | phb = pci_find_hose_for_OF_device(dn); | ||
| 396 | |||
| 397 | if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1) | ||
| 398 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 399 | |||
| 400 | if (bus->number == 0 && PCI_SLOT(devfn) == 0) | ||
| 401 | config_write_pciex_rc(phb->cfg_addr, where, size, val); | ||
| 402 | else | ||
| 403 | config_write_pciex_dev(phb->cfg_addr, bus->number, | ||
| 404 | PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val); | ||
| 405 | return PCIBIOS_SUCCESSFUL; | ||
| 406 | } | ||
| 407 | |||
| 408 | static struct pci_ops scc_pciex_pci_ops = { | ||
| 409 | scc_pciex_read_config, | ||
| 410 | scc_pciex_write_config, | ||
| 411 | }; | ||
| 412 | |||
| 413 | static void pciex_clear_intr_all(unsigned int *base) | ||
| 414 | { | ||
| 415 | PEX_OUT(base, PEXAERRSTS, 0xffffffff); | ||
| 416 | PEX_OUT(base, PEXPRERRSTS, 0xffffffff); | ||
| 417 | PEX_OUT(base, PEXINTSTS, 0xffffffff); | ||
| 418 | } | ||
| 419 | |||
| 420 | #if 0 | ||
| 421 | static void pciex_disable_intr_all(unsigned int *base) | ||
| 422 | { | ||
| 423 | PEX_OUT(base, PEXINTMASK, 0x0); | ||
| 424 | PEX_OUT(base, PEXAERRMASK, 0x0); | ||
| 425 | PEX_OUT(base, PEXPRERRMASK, 0x0); | ||
| 426 | PEX_OUT(base, PEXVDMASK, 0x0); | ||
| 427 | } | ||
| 428 | #endif | ||
| 429 | |||
| 430 | static void pciex_enable_intr_all(unsigned int *base) | ||
| 431 | { | ||
| 432 | PEX_OUT(base, PEXINTMASK, 0x0000e7f1); | ||
| 433 | PEX_OUT(base, PEXAERRMASK, 0x03ff01ff); | ||
| 434 | PEX_OUT(base, PEXPRERRMASK, 0x0001010f); | ||
| 435 | PEX_OUT(base, PEXVDMASK, 0x00000001); | ||
| 436 | } | ||
| 437 | |||
| 438 | static void pciex_check_status(unsigned int *base) | ||
| 439 | { | ||
| 440 | uint32_t err = 0; | ||
| 441 | uint32_t intsts, aerr, prerr, rcvcp, lenerr; | ||
| 442 | uint32_t maea, maec; | ||
| 443 | |||
| 444 | intsts = PEX_IN(base, PEXINTSTS); | ||
| 445 | aerr = PEX_IN(base, PEXAERRSTS); | ||
| 446 | prerr = PEX_IN(base, PEXPRERRSTS); | ||
| 447 | rcvcp = PEX_IN(base, PEXRCVCPLIDA); | ||
| 448 | lenerr = PEX_IN(base, PEXLENERRIDA); | ||
| 449 | |||
| 450 | if (intsts || aerr || prerr || rcvcp || lenerr) | ||
| 451 | err = 1; | ||
| 452 | |||
| 453 | pr_info("PCEXC interrupt!!\n"); | ||
| 454 | pr_info("PEXINTSTS :0x%08x\n", intsts); | ||
| 455 | pr_info("PEXAERRSTS :0x%08x\n", aerr); | ||
| 456 | pr_info("PEXPRERRSTS :0x%08x\n", prerr); | ||
| 457 | pr_info("PEXRCVCPLIDA :0x%08x\n", rcvcp); | ||
| 458 | pr_info("PEXLENERRIDA :0x%08x\n", lenerr); | ||
| 459 | |||
| 460 | /* print detail of Protection Error */ | ||
| 461 | if (intsts & 0x00004000) { | ||
| 462 | uint32_t i, n; | ||
| 463 | for (i = 0; i < 4; i++) { | ||
| 464 | n = 1 << i; | ||
| 465 | if (prerr & n) { | ||
| 466 | maea = PEX_IN(base, PEXMAEA(i)); | ||
| 467 | maec = PEX_IN(base, PEXMAEC(i)); | ||
| 468 | pr_info("PEXMAEC%d :0x%08x\n", i, maec); | ||
| 469 | pr_info("PEXMAEA%d :0x%08x\n", i, maea); | ||
| 470 | } | ||
| 471 | } | ||
| 472 | } | ||
| 473 | |||
| 474 | if (err) | ||
| 475 | pciex_clear_intr_all(base); | ||
| 476 | } | ||
| 477 | |||
| 478 | static irqreturn_t pciex_handle_internal_irq(int irq, void *dev_id) | ||
| 479 | { | ||
| 480 | struct pci_controller *phb = dev_id; | ||
| 481 | |||
| 482 | pr_debug("PCIEX:pciex_handle_internal_irq(irq=%d)\n", irq); | ||
| 483 | |||
| 484 | BUG_ON(phb->cfg_addr == NULL); | ||
| 485 | |||
| 486 | pciex_check_status(phb->cfg_addr); | ||
| 487 | |||
| 488 | return IRQ_HANDLED; | ||
| 489 | } | ||
| 490 | |||
| 491 | static __init int celleb_setup_pciex(struct device_node *node, | ||
| 492 | struct pci_controller *phb) | ||
| 493 | { | ||
| 494 | struct resource r; | ||
| 495 | struct of_irq oirq; | ||
| 496 | int virq; | ||
| 497 | |||
| 498 | /* SMMIO registers; used inside this file */ | ||
| 499 | if (of_address_to_resource(node, 0, &r)) { | ||
| 500 | pr_err("PCIEXC:Failed to get config resource.\n"); | ||
| 501 | return 1; | ||
| 502 | } | ||
| 503 | phb->cfg_addr = ioremap(r.start, r.end - r.start + 1); | ||
| 504 | if (!phb->cfg_addr) { | ||
| 505 | pr_err("PCIEXC:Failed to remap SMMIO region.\n"); | ||
| 506 | return 1; | ||
| 507 | } | ||
| 508 | |||
| 509 | /* Not use cfg_data, cmd and data regs are near address reg */ | ||
| 510 | phb->cfg_data = NULL; | ||
| 511 | |||
| 512 | /* set pci_ops */ | ||
| 513 | phb->ops = &scc_pciex_pci_ops; | ||
| 514 | |||
| 515 | /* internal interrupt handler */ | ||
| 516 | if (of_irq_map_one(node, 1, &oirq)) { | ||
| 517 | pr_err("PCIEXC:Failed to map irq\n"); | ||
| 518 | goto error; | ||
| 519 | } | ||
| 520 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
| 521 | oirq.size); | ||
| 522 | if (request_irq(virq, pciex_handle_internal_irq, | ||
| 523 | IRQF_DISABLED, "pciex", (void *)phb)) { | ||
| 524 | pr_err("PCIEXC:Failed to request irq\n"); | ||
| 525 | goto error; | ||
| 526 | } | ||
| 527 | |||
| 528 | /* enable all interrupts */ | ||
| 529 | pciex_clear_intr_all(phb->cfg_addr); | ||
| 530 | pciex_enable_intr_all(phb->cfg_addr); | ||
| 531 | /* MSI: TBD */ | ||
| 532 | |||
| 533 | return 0; | ||
| 534 | |||
| 535 | error: | ||
| 536 | phb->cfg_data = NULL; | ||
| 537 | if (phb->cfg_addr) | ||
| 538 | iounmap(phb->cfg_addr); | ||
| 539 | phb->cfg_addr = NULL; | ||
| 540 | return 1; | ||
| 541 | } | ||
| 542 | |||
| 543 | struct celleb_phb_spec celleb_pciex_spec __initdata = { | ||
| 544 | .setup = celleb_setup_pciex, | ||
| 545 | .ops = &scc_pciex_ops, | ||
| 546 | .iowa_init = &scc_pciex_iowa_init, | ||
| 547 | }; | ||
diff --git a/arch/powerpc/platforms/celleb/scc_sio.c b/arch/powerpc/platforms/cell/celleb_scc_sio.c index 3a16c5b3c464..3a16c5b3c464 100644 --- a/arch/powerpc/platforms/celleb/scc_sio.c +++ b/arch/powerpc/platforms/cell/celleb_scc_sio.c | |||
diff --git a/arch/powerpc/platforms/celleb/scc_uhc.c b/arch/powerpc/platforms/cell/celleb_scc_uhc.c index cb4307994087..d63b720bfe3a 100644 --- a/arch/powerpc/platforms/celleb/scc_uhc.c +++ b/arch/powerpc/platforms/cell/celleb_scc_uhc.c | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | #include <asm/io.h> | 25 | #include <asm/io.h> |
| 26 | #include <asm/machdep.h> | 26 | #include <asm/machdep.h> |
| 27 | 27 | ||
| 28 | #include "scc.h" | 28 | #include "celleb_scc.h" |
| 29 | 29 | ||
| 30 | #define UHC_RESET_WAIT_MAX 10000 | 30 | #define UHC_RESET_WAIT_MAX 10000 |
| 31 | 31 | ||
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/cell/celleb_setup.c index f27ae1e3fb58..b11cb30decb2 100644 --- a/arch/powerpc/platforms/celleb/setup.c +++ b/arch/powerpc/platforms/cell/celleb_setup.c | |||
| @@ -56,13 +56,13 @@ | |||
| 56 | #include <asm/rtas.h> | 56 | #include <asm/rtas.h> |
| 57 | #include <asm/cell-regs.h> | 57 | #include <asm/cell-regs.h> |
| 58 | 58 | ||
| 59 | #include "interrupt.h" | 59 | #include "beat_interrupt.h" |
| 60 | #include "beat_wrapper.h" | 60 | #include "beat_wrapper.h" |
| 61 | #include "beat.h" | 61 | #include "beat.h" |
| 62 | #include "pci.h" | 62 | #include "celleb_pci.h" |
| 63 | #include "../cell/interrupt.h" | 63 | #include "interrupt.h" |
| 64 | #include "../cell/pervasive.h" | 64 | #include "pervasive.h" |
| 65 | #include "../cell/ras.h" | 65 | #include "ras.h" |
| 66 | 66 | ||
| 67 | static char celleb_machine_type[128] = "Celleb"; | 67 | static char celleb_machine_type[128] = "Celleb"; |
| 68 | 68 | ||
| @@ -114,8 +114,6 @@ static int __init celleb_publish_devices(void) | |||
| 114 | /* Publish OF platform devices for southbridge IOs */ | 114 | /* Publish OF platform devices for southbridge IOs */ |
| 115 | of_platform_bus_probe(NULL, celleb_bus_ids, NULL); | 115 | of_platform_bus_probe(NULL, celleb_bus_ids, NULL); |
| 116 | 116 | ||
| 117 | celleb_pci_workaround_init(); | ||
| 118 | |||
| 119 | return 0; | 117 | return 0; |
| 120 | } | 118 | } |
| 121 | machine_device_initcall(celleb_beat, celleb_publish_devices); | 119 | machine_device_initcall(celleb_beat, celleb_publish_devices); |
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c index 979d4b67efb4..3b84e8be314c 100644 --- a/arch/powerpc/platforms/cell/io-workarounds.c +++ b/arch/powerpc/platforms/cell/io-workarounds.c | |||
| @@ -1,6 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Support PCI IO workaround | ||
| 3 | * | ||
| 2 | * Copyright (C) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org> | 4 | * Copyright (C) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org> |
| 3 | * IBM, Corp. | 5 | * IBM, Corp. |
| 6 | * (C) Copyright 2007-2008 TOSHIBA CORPORATION | ||
| 4 | * | 7 | * |
| 5 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
| @@ -9,335 +12,174 @@ | |||
| 9 | #undef DEBUG | 12 | #undef DEBUG |
| 10 | 13 | ||
| 11 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 12 | #include <linux/mm.h> | 15 | |
| 13 | #include <linux/pci.h> | ||
| 14 | #include <asm/io.h> | 16 | #include <asm/io.h> |
| 15 | #include <asm/machdep.h> | 17 | #include <asm/machdep.h> |
| 16 | #include <asm/pci-bridge.h> | 18 | #include <asm/pgtable.h> |
| 17 | #include <asm/ppc-pci.h> | 19 | #include <asm/ppc-pci.h> |
| 18 | 20 | ||
| 21 | #include "io-workarounds.h" | ||
| 19 | 22 | ||
| 20 | #define SPIDER_PCI_REG_BASE 0xd000 | 23 | #define IOWA_MAX_BUS 8 |
| 21 | #define SPIDER_PCI_VCI_CNTL_STAT 0x0110 | ||
| 22 | #define SPIDER_PCI_DUMMY_READ 0x0810 | ||
| 23 | #define SPIDER_PCI_DUMMY_READ_BASE 0x0814 | ||
| 24 | 24 | ||
| 25 | /* Undefine that to re-enable bogus prefetch | 25 | static struct iowa_bus iowa_busses[IOWA_MAX_BUS]; |
| 26 | * | 26 | static unsigned int iowa_bus_count; |
| 27 | * Without that workaround, the chip will do bogus prefetch past | ||
| 28 | * page boundary from system memory. This setting will disable that, | ||
| 29 | * though the documentation is unclear as to the consequences of doing | ||
| 30 | * so, either purely performances, or possible misbehaviour... It's not | ||
| 31 | * clear wether the chip can handle unaligned accesses at all without | ||
| 32 | * prefetching enabled. | ||
| 33 | * | ||
| 34 | * For now, things appear to be behaving properly with that prefetching | ||
| 35 | * disabled and IDE, possibly because IDE isn't doing any unaligned | ||
| 36 | * access. | ||
| 37 | */ | ||
| 38 | #define SPIDER_DISABLE_PREFETCH | ||
| 39 | 27 | ||
| 40 | #define MAX_SPIDERS 3 | 28 | static struct iowa_bus *iowa_pci_find(unsigned long vaddr, unsigned long paddr) |
| 29 | { | ||
| 30 | int i, j; | ||
| 31 | struct resource *res; | ||
| 32 | unsigned long vstart, vend; | ||
| 41 | 33 | ||
| 42 | static struct spider_pci_bus { | 34 | for (i = 0; i < iowa_bus_count; i++) { |
| 43 | void __iomem *regs; | 35 | struct iowa_bus *bus = &iowa_busses[i]; |
| 44 | unsigned long mmio_start; | 36 | struct pci_controller *phb = bus->phb; |
| 45 | unsigned long mmio_end; | ||
| 46 | unsigned long pio_vstart; | ||
| 47 | unsigned long pio_vend; | ||
| 48 | } spider_pci_busses[MAX_SPIDERS]; | ||
| 49 | static int spider_pci_count; | ||
| 50 | 37 | ||
| 51 | static struct spider_pci_bus *spider_pci_find(unsigned long vaddr, | 38 | if (vaddr) { |
| 52 | unsigned long paddr) | 39 | vstart = (unsigned long)phb->io_base_virt; |
| 53 | { | 40 | vend = vstart + phb->pci_io_size - 1; |
| 54 | int i; | 41 | if ((vaddr >= vstart) && (vaddr <= vend)) |
| 55 | 42 | return bus; | |
| 56 | for (i = 0; i < spider_pci_count; i++) { | 43 | } |
| 57 | struct spider_pci_bus *bus = &spider_pci_busses[i]; | 44 | |
| 58 | if (paddr && paddr >= bus->mmio_start && paddr < bus->mmio_end) | 45 | if (paddr) |
| 59 | return bus; | 46 | for (j = 0; j < 3; j++) { |
| 60 | if (vaddr && vaddr >= bus->pio_vstart && vaddr < bus->pio_vend) | 47 | res = &phb->mem_resources[j]; |
| 61 | return bus; | 48 | if (paddr >= res->start && paddr <= res->end) |
| 49 | return bus; | ||
| 50 | } | ||
| 62 | } | 51 | } |
| 52 | |||
| 63 | return NULL; | 53 | return NULL; |
| 64 | } | 54 | } |
| 65 | 55 | ||
| 66 | static void spider_io_flush(const volatile void __iomem *addr) | 56 | struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR addr) |
| 67 | { | 57 | { |
| 68 | struct spider_pci_bus *bus; | 58 | struct iowa_bus *bus; |
| 69 | int token; | 59 | int token; |
| 70 | 60 | ||
| 71 | /* Get platform token (set by ioremap) from address */ | ||
| 72 | token = PCI_GET_ADDR_TOKEN(addr); | 61 | token = PCI_GET_ADDR_TOKEN(addr); |
| 73 | 62 | ||
| 74 | /* Fast path if we have a non-0 token, it indicates which bus we | 63 | if (token && token <= iowa_bus_count) |
| 75 | * are on. | 64 | bus = &iowa_busses[token - 1]; |
| 76 | * | ||
| 77 | * If the token is 0, that means either that the ioremap was done | ||
| 78 | * before we initialized this layer, or it's a PIO operation. We | ||
| 79 | * fallback to a low path in this case. Hopefully, internal devices | ||
| 80 | * which are ioremap'ed early should use in_XX/out_XX functions | ||
| 81 | * instead of the PCI ones and thus not suffer from the slowdown. | ||
| 82 | * | ||
| 83 | * Also note that currently, the workaround will not work for areas | ||
| 84 | * that are not mapped with PTEs (bolted in the hash table). This | ||
| 85 | * is the case for ioremaps done very early at boot (before | ||
| 86 | * mem_init_done) and includes the mapping of the ISA IO space. | ||
| 87 | * | ||
| 88 | * Fortunately, none of the affected devices is expected to do DMA | ||
| 89 | * and thus there should be no problem in practice. | ||
| 90 | * | ||
| 91 | * In order to improve performances, we only do the PTE search for | ||
| 92 | * addresses falling in the PHB IO space area. That means it will | ||
| 93 | * not work for hotplug'ed PHBs but those don't exist with Spider. | ||
| 94 | */ | ||
| 95 | if (token && token <= spider_pci_count) | ||
| 96 | bus = &spider_pci_busses[token - 1]; | ||
| 97 | else { | 65 | else { |
| 98 | unsigned long vaddr, paddr; | 66 | unsigned long vaddr, paddr; |
| 99 | pte_t *ptep; | 67 | pte_t *ptep; |
| 100 | 68 | ||
| 101 | /* Fixup physical address */ | ||
| 102 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); | 69 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); |
| 70 | if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END) | ||
| 71 | return NULL; | ||
| 103 | 72 | ||
| 104 | /* Check if it's in allowed range for PIO */ | ||
| 105 | if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END) | ||
| 106 | return; | ||
| 107 | |||
| 108 | /* Try to find a PTE. If not, clear the paddr, we'll do | ||
| 109 | * a vaddr only lookup (PIO only) | ||
| 110 | */ | ||
| 111 | ptep = find_linux_pte(init_mm.pgd, vaddr); | 73 | ptep = find_linux_pte(init_mm.pgd, vaddr); |
| 112 | if (ptep == NULL) | 74 | if (ptep == NULL) |
| 113 | paddr = 0; | 75 | paddr = 0; |
| 114 | else | 76 | else |
| 115 | paddr = pte_pfn(*ptep) << PAGE_SHIFT; | 77 | paddr = pte_pfn(*ptep) << PAGE_SHIFT; |
| 78 | bus = iowa_pci_find(vaddr, paddr); | ||
| 116 | 79 | ||
| 117 | bus = spider_pci_find(vaddr, paddr); | ||
| 118 | if (bus == NULL) | 80 | if (bus == NULL) |
| 119 | return; | 81 | return NULL; |
| 120 | } | 82 | } |
| 121 | 83 | ||
| 122 | /* Now do the workaround | 84 | return bus; |
| 123 | */ | ||
| 124 | (void)in_be32(bus->regs + SPIDER_PCI_DUMMY_READ); | ||
| 125 | } | 85 | } |
| 126 | 86 | ||
| 127 | static u8 spider_readb(const volatile void __iomem *addr) | 87 | struct iowa_bus *iowa_pio_find_bus(unsigned long port) |
| 128 | { | 88 | { |
| 129 | u8 val = __do_readb(addr); | 89 | unsigned long vaddr = (unsigned long)pci_io_base + port; |
| 130 | spider_io_flush(addr); | 90 | return iowa_pci_find(vaddr, 0); |
| 131 | return val; | ||
| 132 | } | 91 | } |
| 133 | 92 | ||
| 134 | static u16 spider_readw(const volatile void __iomem *addr) | ||
| 135 | { | ||
| 136 | u16 val = __do_readw(addr); | ||
| 137 | spider_io_flush(addr); | ||
| 138 | return val; | ||
| 139 | } | ||
| 140 | 93 | ||
| 141 | static u32 spider_readl(const volatile void __iomem *addr) | 94 | #define DEF_PCI_AC_RET(name, ret, at, al, space, aa) \ |
| 142 | { | 95 | static ret iowa_##name at \ |
| 143 | u32 val = __do_readl(addr); | 96 | { \ |
| 144 | spider_io_flush(addr); | 97 | struct iowa_bus *bus; \ |
| 145 | return val; | 98 | bus = iowa_##space##_find_bus(aa); \ |
| 99 | if (bus && bus->ops && bus->ops->name) \ | ||
| 100 | return bus->ops->name al; \ | ||
| 101 | return __do_##name al; \ | ||
| 146 | } | 102 | } |
| 147 | 103 | ||
| 148 | static u64 spider_readq(const volatile void __iomem *addr) | 104 | #define DEF_PCI_AC_NORET(name, at, al, space, aa) \ |
| 149 | { | 105 | static void iowa_##name at \ |
| 150 | u64 val = __do_readq(addr); | 106 | { \ |
| 151 | spider_io_flush(addr); | 107 | struct iowa_bus *bus; \ |
| 152 | return val; | 108 | bus = iowa_##space##_find_bus(aa); \ |
| 109 | if (bus && bus->ops && bus->ops->name) { \ | ||
| 110 | bus->ops->name al; \ | ||
| 111 | return; \ | ||
| 112 | } \ | ||
| 113 | __do_##name al; \ | ||
| 153 | } | 114 | } |
| 154 | 115 | ||
| 155 | static u16 spider_readw_be(const volatile void __iomem *addr) | 116 | #include <asm/io-defs.h> |
| 156 | { | ||
| 157 | u16 val = __do_readw_be(addr); | ||
| 158 | spider_io_flush(addr); | ||
| 159 | return val; | ||
| 160 | } | ||
| 161 | 117 | ||
| 162 | static u32 spider_readl_be(const volatile void __iomem *addr) | 118 | #undef DEF_PCI_AC_RET |
| 163 | { | 119 | #undef DEF_PCI_AC_NORET |
| 164 | u32 val = __do_readl_be(addr); | ||
| 165 | spider_io_flush(addr); | ||
| 166 | return val; | ||
| 167 | } | ||
| 168 | 120 | ||
| 169 | static u64 spider_readq_be(const volatile void __iomem *addr) | 121 | static struct ppc_pci_io __initdata iowa_pci_io = { |
| 170 | { | ||
| 171 | u64 val = __do_readq_be(addr); | ||
| 172 | spider_io_flush(addr); | ||
| 173 | return val; | ||
| 174 | } | ||
| 175 | 122 | ||
| 176 | static void spider_readsb(const volatile void __iomem *addr, void *buf, | 123 | #define DEF_PCI_AC_RET(name, ret, at, al, space, aa) .name = iowa_##name, |
| 177 | unsigned long count) | 124 | #define DEF_PCI_AC_NORET(name, at, al, space, aa) .name = iowa_##name, |
| 178 | { | ||
| 179 | __do_readsb(addr, buf, count); | ||
| 180 | spider_io_flush(addr); | ||
| 181 | } | ||
| 182 | 125 | ||
| 183 | static void spider_readsw(const volatile void __iomem *addr, void *buf, | 126 | #include <asm/io-defs.h> |
| 184 | unsigned long count) | ||
| 185 | { | ||
| 186 | __do_readsw(addr, buf, count); | ||
| 187 | spider_io_flush(addr); | ||
| 188 | } | ||
| 189 | 127 | ||
| 190 | static void spider_readsl(const volatile void __iomem *addr, void *buf, | 128 | #undef DEF_PCI_AC_RET |
| 191 | unsigned long count) | 129 | #undef DEF_PCI_AC_NORET |
| 192 | { | ||
| 193 | __do_readsl(addr, buf, count); | ||
| 194 | spider_io_flush(addr); | ||
| 195 | } | ||
| 196 | |||
| 197 | static void spider_memcpy_fromio(void *dest, const volatile void __iomem *src, | ||
| 198 | unsigned long n) | ||
| 199 | { | ||
| 200 | __do_memcpy_fromio(dest, src, n); | ||
| 201 | spider_io_flush(src); | ||
| 202 | } | ||
| 203 | 130 | ||
| 131 | }; | ||
| 204 | 132 | ||
| 205 | static void __iomem * spider_ioremap(unsigned long addr, unsigned long size, | 133 | static void __iomem *iowa_ioremap(unsigned long addr, unsigned long size, |
| 206 | unsigned long flags) | 134 | unsigned long flags) |
| 207 | { | 135 | { |
| 208 | struct spider_pci_bus *bus; | 136 | struct iowa_bus *bus; |
| 209 | void __iomem *res = __ioremap(addr, size, flags); | 137 | void __iomem *res = __ioremap(addr, size, flags); |
| 210 | int busno; | 138 | int busno; |
| 211 | 139 | ||
| 212 | pr_debug("spider_ioremap(0x%lx, 0x%lx, 0x%lx) -> 0x%p\n", | 140 | bus = iowa_pci_find(0, addr); |
| 213 | addr, size, flags, res); | ||
| 214 | |||
| 215 | bus = spider_pci_find(0, addr); | ||
| 216 | if (bus != NULL) { | 141 | if (bus != NULL) { |
| 217 | busno = bus - spider_pci_busses; | 142 | busno = bus - iowa_busses; |
| 218 | pr_debug(" found bus %d, setting token\n", busno); | ||
| 219 | PCI_SET_ADDR_TOKEN(res, busno + 1); | 143 | PCI_SET_ADDR_TOKEN(res, busno + 1); |
| 220 | } | 144 | } |
| 221 | pr_debug(" result=0x%p\n", res); | ||
| 222 | |||
| 223 | return res; | 145 | return res; |
| 224 | } | 146 | } |
| 225 | 147 | ||
| 226 | static void __init spider_pci_setup_chip(struct spider_pci_bus *bus) | 148 | /* Regist new bus to support workaround */ |
| 227 | { | 149 | void __init iowa_register_bus(struct pci_controller *phb, |
| 228 | #ifdef SPIDER_DISABLE_PREFETCH | 150 | struct ppc_pci_io *ops, |
| 229 | u32 val = in_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT); | 151 | int (*initfunc)(struct iowa_bus *, void *), void *data) |
| 230 | pr_debug(" PVCI_Control_Status was 0x%08x\n", val); | ||
| 231 | out_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8); | ||
| 232 | #endif | ||
| 233 | |||
| 234 | /* Configure the dummy address for the workaround */ | ||
| 235 | out_be32(bus->regs + SPIDER_PCI_DUMMY_READ_BASE, 0x80000000); | ||
| 236 | } | ||
| 237 | |||
| 238 | static void __init spider_pci_add_one(struct pci_controller *phb) | ||
| 239 | { | 152 | { |
| 240 | struct spider_pci_bus *bus = &spider_pci_busses[spider_pci_count]; | 153 | struct iowa_bus *bus; |
| 241 | struct device_node *np = phb->dn; | 154 | struct device_node *np = phb->dn; |
| 242 | struct resource rsrc; | ||
| 243 | void __iomem *regs; | ||
| 244 | 155 | ||
| 245 | if (spider_pci_count >= MAX_SPIDERS) { | 156 | if (iowa_bus_count >= IOWA_MAX_BUS) { |
| 246 | printk(KERN_ERR "Too many spider bridges, workarounds" | 157 | pr_err("IOWA:Too many pci bridges, " |
| 247 | " disabled for %s\n", np->full_name); | 158 | "workarounds disabled for %s\n", np->full_name); |
| 248 | return; | 159 | return; |
| 249 | } | 160 | } |
| 250 | 161 | ||
| 251 | /* Get the registers for the beast */ | 162 | bus = &iowa_busses[iowa_bus_count]; |
| 252 | if (of_address_to_resource(np, 0, &rsrc)) { | 163 | bus->phb = phb; |
| 253 | printk(KERN_ERR "Failed to get registers for spider %s" | 164 | bus->ops = ops; |
| 254 | " workarounds disabled\n", np->full_name); | ||
| 255 | return; | ||
| 256 | } | ||
| 257 | 165 | ||
| 258 | /* Mask out some useless bits in there to get to the base of the | 166 | if (initfunc) |
| 259 | * spider chip | 167 | if ((*initfunc)(bus, data)) |
| 260 | */ | 168 | return; |
| 261 | rsrc.start &= ~0xfffffffful; | ||
| 262 | |||
| 263 | /* Map them */ | ||
| 264 | regs = ioremap(rsrc.start + SPIDER_PCI_REG_BASE, 0x1000); | ||
| 265 | if (regs == NULL) { | ||
| 266 | printk(KERN_ERR "Failed to map registers for spider %s" | ||
| 267 | " workarounds disabled\n", np->full_name); | ||
| 268 | return; | ||
| 269 | } | ||
| 270 | |||
| 271 | spider_pci_count++; | ||
| 272 | |||
| 273 | /* We assume spiders only have one MMIO resource */ | ||
| 274 | bus->mmio_start = phb->mem_resources[0].start; | ||
| 275 | bus->mmio_end = phb->mem_resources[0].end + 1; | ||
| 276 | |||
| 277 | bus->pio_vstart = (unsigned long)phb->io_base_virt; | ||
| 278 | bus->pio_vend = bus->pio_vstart + phb->pci_io_size; | ||
| 279 | |||
| 280 | bus->regs = regs; | ||
| 281 | |||
| 282 | printk(KERN_INFO "PCI: Spider MMIO workaround for %s\n",np->full_name); | ||
| 283 | 169 | ||
| 284 | pr_debug(" mmio (P) = 0x%016lx..0x%016lx\n", | 170 | iowa_bus_count++; |
| 285 | bus->mmio_start, bus->mmio_end); | ||
| 286 | pr_debug(" pio (V) = 0x%016lx..0x%016lx\n", | ||
| 287 | bus->pio_vstart, bus->pio_vend); | ||
| 288 | pr_debug(" regs (P) = 0x%016lx (V) = 0x%p\n", | ||
| 289 | rsrc.start + SPIDER_PCI_REG_BASE, bus->regs); | ||
| 290 | 171 | ||
| 291 | spider_pci_setup_chip(bus); | 172 | pr_debug("IOWA:[%d]Add bus, %s.\n", iowa_bus_count-1, np->full_name); |
| 292 | } | 173 | } |
| 293 | 174 | ||
| 294 | static struct ppc_pci_io __initdata spider_pci_io = { | 175 | /* enable IO workaround */ |
| 295 | .readb = spider_readb, | 176 | void __init io_workaround_init(void) |
| 296 | .readw = spider_readw, | ||
| 297 | .readl = spider_readl, | ||
| 298 | .readq = spider_readq, | ||
| 299 | .readw_be = spider_readw_be, | ||
| 300 | .readl_be = spider_readl_be, | ||
| 301 | .readq_be = spider_readq_be, | ||
| 302 | .readsb = spider_readsb, | ||
| 303 | .readsw = spider_readsw, | ||
| 304 | .readsl = spider_readsl, | ||
| 305 | .memcpy_fromio = spider_memcpy_fromio, | ||
| 306 | }; | ||
| 307 | |||
| 308 | static int __init spider_pci_workaround_init(void) | ||
| 309 | { | 177 | { |
| 310 | struct pci_controller *phb; | 178 | static int io_workaround_inited; |
| 311 | |||
| 312 | /* Find spider bridges. We assume they have been all probed | ||
| 313 | * in setup_arch(). If that was to change, we would need to | ||
| 314 | * update this code to cope with dynamically added busses | ||
| 315 | */ | ||
| 316 | list_for_each_entry(phb, &hose_list, list_node) { | ||
| 317 | struct device_node *np = phb->dn; | ||
| 318 | const char *model = of_get_property(np, "model", NULL); | ||
| 319 | |||
| 320 | /* If no model property or name isn't exactly "pci", skip */ | ||
| 321 | if (model == NULL || strcmp(np->name, "pci")) | ||
| 322 | continue; | ||
| 323 | /* If model is not "Spider", skip */ | ||
| 324 | if (strcmp(model, "Spider")) | ||
| 325 | continue; | ||
| 326 | spider_pci_add_one(phb); | ||
| 327 | } | ||
| 328 | |||
| 329 | /* No Spider PCI found, exit */ | ||
| 330 | if (spider_pci_count == 0) | ||
| 331 | return 0; | ||
| 332 | 179 | ||
| 333 | /* Setup IO callbacks. We only setup MMIO reads. PIO reads will | 180 | if (io_workaround_inited) |
| 334 | * fallback to MMIO reads (though without a token, thus slower) | 181 | return; |
| 335 | */ | 182 | ppc_pci_io = iowa_pci_io; |
| 336 | ppc_pci_io = spider_pci_io; | 183 | ppc_md.ioremap = iowa_ioremap; |
| 337 | 184 | io_workaround_inited = 1; | |
| 338 | /* Setup ioremap callback */ | ||
| 339 | ppc_md.ioremap = spider_ioremap; | ||
| 340 | |||
| 341 | return 0; | ||
| 342 | } | 185 | } |
| 343 | machine_arch_initcall(cell, spider_pci_workaround_init); | ||
diff --git a/arch/powerpc/platforms/cell/io-workarounds.h b/arch/powerpc/platforms/cell/io-workarounds.h new file mode 100644 index 000000000000..79d8ed3d510f --- /dev/null +++ b/arch/powerpc/platforms/cell/io-workarounds.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | /* | ||
| 2 | * Support PCI IO workaround | ||
| 3 | * | ||
| 4 | * (C) Copyright 2007-2008 TOSHIBA CORPORATION | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef _IO_WORKAROUNDS_H | ||
| 22 | #define _IO_WORKAROUNDS_H | ||
| 23 | |||
| 24 | #include <linux/io.h> | ||
| 25 | #include <asm/pci-bridge.h> | ||
| 26 | |||
| 27 | /* Bus info */ | ||
| 28 | struct iowa_bus { | ||
| 29 | struct pci_controller *phb; | ||
| 30 | struct ppc_pci_io *ops; | ||
| 31 | void *private; | ||
| 32 | }; | ||
| 33 | |||
| 34 | void __init io_workaround_init(void); | ||
| 35 | void __init iowa_register_bus(struct pci_controller *, struct ppc_pci_io *, | ||
| 36 | int (*)(struct iowa_bus *, void *), void *); | ||
| 37 | struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR); | ||
| 38 | struct iowa_bus *iowa_pio_find_bus(unsigned long); | ||
| 39 | |||
| 40 | extern struct ppc_pci_io spiderpci_ops; | ||
| 41 | extern int spiderpci_iowa_init(struct iowa_bus *, void *); | ||
| 42 | |||
| 43 | #define SPIDER_PCI_REG_BASE 0xd000 | ||
| 44 | #define SPIDER_PCI_REG_SIZE 0x1000 | ||
| 45 | #define SPIDER_PCI_VCI_CNTL_STAT 0x0110 | ||
| 46 | #define SPIDER_PCI_DUMMY_READ 0x0810 | ||
| 47 | #define SPIDER_PCI_DUMMY_READ_BASE 0x0814 | ||
| 48 | |||
| 49 | #endif /* _IO_WORKAROUNDS_H */ | ||
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 5c531e8f9f6f..ab721b50fbba 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c | |||
| @@ -57,6 +57,7 @@ | |||
| 57 | #include "interrupt.h" | 57 | #include "interrupt.h" |
| 58 | #include "pervasive.h" | 58 | #include "pervasive.h" |
| 59 | #include "ras.h" | 59 | #include "ras.h" |
| 60 | #include "io-workarounds.h" | ||
| 60 | 61 | ||
| 61 | #ifdef DEBUG | 62 | #ifdef DEBUG |
| 62 | #define DBG(fmt...) udbg_printf(fmt) | 63 | #define DBG(fmt...) udbg_printf(fmt) |
| @@ -117,13 +118,50 @@ static void cell_fixup_pcie_rootcomplex(struct pci_dev *dev) | |||
| 117 | } | 118 | } |
| 118 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, cell_fixup_pcie_rootcomplex); | 119 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, cell_fixup_pcie_rootcomplex); |
| 119 | 120 | ||
| 121 | static int __devinit cell_setup_phb(struct pci_controller *phb) | ||
| 122 | { | ||
| 123 | const char *model; | ||
| 124 | struct device_node *np; | ||
| 125 | |||
| 126 | int rc = rtas_setup_phb(phb); | ||
| 127 | if (rc) | ||
| 128 | return rc; | ||
| 129 | |||
| 130 | np = phb->dn; | ||
| 131 | model = of_get_property(np, "model", NULL); | ||
| 132 | if (model == NULL || strcmp(np->name, "pci")) | ||
| 133 | return 0; | ||
| 134 | |||
| 135 | /* Setup workarounds for spider */ | ||
| 136 | if (strcmp(model, "Spider")) | ||
| 137 | return 0; | ||
| 138 | |||
| 139 | iowa_register_bus(phb, &spiderpci_ops, &spiderpci_iowa_init, | ||
| 140 | (void *)SPIDER_PCI_REG_BASE); | ||
| 141 | io_workaround_init(); | ||
| 142 | |||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | |||
| 120 | static int __init cell_publish_devices(void) | 146 | static int __init cell_publish_devices(void) |
| 121 | { | 147 | { |
| 148 | struct device_node *root = of_find_node_by_path("/"); | ||
| 149 | struct device_node *np; | ||
| 122 | int node; | 150 | int node; |
| 123 | 151 | ||
| 124 | /* Publish OF platform devices for southbridge IOs */ | 152 | /* Publish OF platform devices for southbridge IOs */ |
| 125 | of_platform_bus_probe(NULL, NULL, NULL); | 153 | of_platform_bus_probe(NULL, NULL, NULL); |
| 126 | 154 | ||
| 155 | /* On spider based blades, we need to manually create the OF | ||
| 156 | * platform devices for the PCI host bridges | ||
| 157 | */ | ||
| 158 | for_each_child_of_node(root, np) { | ||
| 159 | if (np->type == NULL || (strcmp(np->type, "pci") != 0 && | ||
| 160 | strcmp(np->type, "pciex") != 0)) | ||
| 161 | continue; | ||
| 162 | of_platform_device_create(np, NULL, NULL); | ||
| 163 | } | ||
| 164 | |||
| 127 | /* There is no device for the MIC memory controller, thus we create | 165 | /* There is no device for the MIC memory controller, thus we create |
| 128 | * a platform device for it to attach the EDAC driver to. | 166 | * a platform device for it to attach the EDAC driver to. |
| 129 | */ | 167 | */ |
| @@ -132,6 +170,7 @@ static int __init cell_publish_devices(void) | |||
| 132 | continue; | 170 | continue; |
| 133 | platform_device_register_simple("cbe-mic", node, NULL, 0); | 171 | platform_device_register_simple("cbe-mic", node, NULL, 0); |
| 134 | } | 172 | } |
| 173 | |||
| 135 | return 0; | 174 | return 0; |
| 136 | } | 175 | } |
| 137 | machine_subsys_initcall(cell, cell_publish_devices); | 176 | machine_subsys_initcall(cell, cell_publish_devices); |
| @@ -213,7 +252,7 @@ static void __init cell_setup_arch(void) | |||
| 213 | 252 | ||
| 214 | /* Find and initialize PCI host bridges */ | 253 | /* Find and initialize PCI host bridges */ |
| 215 | init_pci_config_tokens(); | 254 | init_pci_config_tokens(); |
| 216 | find_and_init_phbs(); | 255 | |
| 217 | cbe_pervasive_init(); | 256 | cbe_pervasive_init(); |
| 218 | #ifdef CONFIG_DUMMY_CONSOLE | 257 | #ifdef CONFIG_DUMMY_CONSOLE |
| 219 | conswitchp = &dummy_con; | 258 | conswitchp = &dummy_con; |
| @@ -249,7 +288,7 @@ define_machine(cell) { | |||
| 249 | .calibrate_decr = generic_calibrate_decr, | 288 | .calibrate_decr = generic_calibrate_decr, |
| 250 | .progress = cell_progress, | 289 | .progress = cell_progress, |
| 251 | .init_IRQ = cell_init_irq, | 290 | .init_IRQ = cell_init_irq, |
| 252 | .pci_setup_phb = rtas_setup_phb, | 291 | .pci_setup_phb = cell_setup_phb, |
| 253 | #ifdef CONFIG_KEXEC | 292 | #ifdef CONFIG_KEXEC |
| 254 | .machine_kexec = default_machine_kexec, | 293 | .machine_kexec = default_machine_kexec, |
| 255 | .machine_kexec_prepare = default_machine_kexec_prepare, | 294 | .machine_kexec_prepare = default_machine_kexec_prepare, |
diff --git a/arch/powerpc/platforms/cell/spider-pci.c b/arch/powerpc/platforms/cell/spider-pci.c new file mode 100644 index 000000000000..418b605ac35a --- /dev/null +++ b/arch/powerpc/platforms/cell/spider-pci.c | |||
| @@ -0,0 +1,184 @@ | |||
| 1 | /* | ||
| 2 | * IO workarounds for PCI on Celleb/Cell platform | ||
| 3 | * | ||
| 4 | * (C) Copyright 2006-2007 TOSHIBA CORPORATION | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #undef DEBUG | ||
| 22 | |||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/of_platform.h> | ||
| 25 | #include <linux/io.h> | ||
| 26 | |||
| 27 | #include <asm/ppc-pci.h> | ||
| 28 | #include <asm/pci-bridge.h> | ||
| 29 | |||
| 30 | #include "io-workarounds.h" | ||
| 31 | |||
| 32 | #define SPIDER_PCI_DISABLE_PREFETCH | ||
| 33 | |||
| 34 | struct spiderpci_iowa_private { | ||
| 35 | void __iomem *regs; | ||
| 36 | }; | ||
| 37 | |||
| 38 | static void spiderpci_io_flush(struct iowa_bus *bus) | ||
| 39 | { | ||
| 40 | struct spiderpci_iowa_private *priv; | ||
| 41 | u32 val; | ||
| 42 | |||
| 43 | priv = bus->private; | ||
| 44 | val = in_be32(priv->regs + SPIDER_PCI_DUMMY_READ); | ||
| 45 | iosync(); | ||
| 46 | } | ||
| 47 | |||
| 48 | #define SPIDER_PCI_MMIO_READ(name, ret) \ | ||
| 49 | static ret spiderpci_##name(const PCI_IO_ADDR addr) \ | ||
| 50 | { \ | ||
| 51 | ret val = __do_##name(addr); \ | ||
| 52 | spiderpci_io_flush(iowa_mem_find_bus(addr)); \ | ||
| 53 | return val; \ | ||
| 54 | } | ||
| 55 | |||
| 56 | #define SPIDER_PCI_MMIO_READ_STR(name) \ | ||
| 57 | static void spiderpci_##name(const PCI_IO_ADDR addr, void *buf, \ | ||
| 58 | unsigned long count) \ | ||
| 59 | { \ | ||
| 60 | __do_##name(addr, buf, count); \ | ||
| 61 | spiderpci_io_flush(iowa_mem_find_bus(addr)); \ | ||
| 62 | } | ||
| 63 | |||
| 64 | SPIDER_PCI_MMIO_READ(readb, u8) | ||
| 65 | SPIDER_PCI_MMIO_READ(readw, u16) | ||
| 66 | SPIDER_PCI_MMIO_READ(readl, u32) | ||
| 67 | SPIDER_PCI_MMIO_READ(readq, u64) | ||
| 68 | SPIDER_PCI_MMIO_READ(readw_be, u16) | ||
| 69 | SPIDER_PCI_MMIO_READ(readl_be, u32) | ||
| 70 | SPIDER_PCI_MMIO_READ(readq_be, u64) | ||
| 71 | SPIDER_PCI_MMIO_READ_STR(readsb) | ||
| 72 | SPIDER_PCI_MMIO_READ_STR(readsw) | ||
| 73 | SPIDER_PCI_MMIO_READ_STR(readsl) | ||
| 74 | |||
| 75 | static void spiderpci_memcpy_fromio(void *dest, const PCI_IO_ADDR src, | ||
| 76 | unsigned long n) | ||
| 77 | { | ||
| 78 | __do_memcpy_fromio(dest, src, n); | ||
| 79 | spiderpci_io_flush(iowa_mem_find_bus(src)); | ||
| 80 | } | ||
| 81 | |||
| 82 | static int __init spiderpci_pci_setup_chip(struct pci_controller *phb, | ||
| 83 | void __iomem *regs) | ||
| 84 | { | ||
| 85 | void *dummy_page_va; | ||
| 86 | dma_addr_t dummy_page_da; | ||
| 87 | |||
| 88 | #ifdef SPIDER_PCI_DISABLE_PREFETCH | ||
| 89 | u32 val = in_be32(regs + SPIDER_PCI_VCI_CNTL_STAT); | ||
| 90 | pr_debug("SPIDER_IOWA:PVCI_Control_Status was 0x%08x\n", val); | ||
| 91 | out_be32(regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8); | ||
| 92 | #endif /* SPIDER_PCI_DISABLE_PREFETCH */ | ||
| 93 | |||
| 94 | /* setup dummy read */ | ||
| 95 | /* | ||
| 96 | * On CellBlade, we can't know that which XDR memory is used by | ||
| 97 | * kmalloc() to allocate dummy_page_va. | ||
| 98 | * In order to imporve the performance, the XDR which is used to | ||
| 99 | * allocate dummy_page_va is the nearest the spider-pci. | ||
| 100 | * We have to select the CBE which is the nearest the spider-pci | ||
| 101 | * to allocate memory from the best XDR, but I don't know that | ||
| 102 | * how to do. | ||
| 103 | * | ||
| 104 | * Celleb does not have this problem, because it has only one XDR. | ||
| 105 | */ | ||
| 106 | dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 107 | if (!dummy_page_va) { | ||
| 108 | pr_err("SPIDERPCI-IOWA:Alloc dummy_page_va failed.\n"); | ||
| 109 | return -1; | ||
| 110 | } | ||
| 111 | |||
| 112 | dummy_page_da = dma_map_single(phb->parent, dummy_page_va, | ||
| 113 | PAGE_SIZE, DMA_FROM_DEVICE); | ||
| 114 | if (dma_mapping_error(dummy_page_da)) { | ||
| 115 | pr_err("SPIDER-IOWA:Map dummy page filed.\n"); | ||
| 116 | kfree(dummy_page_va); | ||
| 117 | return -1; | ||
| 118 | } | ||
| 119 | |||
| 120 | out_be32(regs + SPIDER_PCI_DUMMY_READ_BASE, dummy_page_da); | ||
| 121 | |||
| 122 | return 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | int __init spiderpci_iowa_init(struct iowa_bus *bus, void *data) | ||
| 126 | { | ||
| 127 | void __iomem *regs = NULL; | ||
| 128 | struct spiderpci_iowa_private *priv; | ||
| 129 | struct device_node *np = bus->phb->dn; | ||
| 130 | struct resource r; | ||
| 131 | unsigned long offset = (unsigned long)data; | ||
| 132 | |||
| 133 | pr_debug("SPIDERPCI-IOWA:Bus initialize for spider(%s)\n", | ||
| 134 | np->full_name); | ||
| 135 | |||
| 136 | priv = kzalloc(sizeof(struct spiderpci_iowa_private), GFP_KERNEL); | ||
| 137 | if (!priv) { | ||
| 138 | pr_err("SPIDERPCI-IOWA:" | ||
| 139 | "Can't allocate struct spiderpci_iowa_private"); | ||
| 140 | return -1; | ||
| 141 | } | ||
| 142 | |||
| 143 | if (of_address_to_resource(np, 0, &r)) { | ||
| 144 | pr_err("SPIDERPCI-IOWA:Can't get resource.\n"); | ||
| 145 | goto error; | ||
| 146 | } | ||
| 147 | |||
| 148 | regs = ioremap(r.start + offset, SPIDER_PCI_REG_SIZE); | ||
| 149 | if (!regs) { | ||
| 150 | pr_err("SPIDERPCI-IOWA:ioremap failed.\n"); | ||
| 151 | goto error; | ||
| 152 | } | ||
| 153 | priv->regs = regs; | ||
| 154 | bus->private = priv; | ||
| 155 | |||
| 156 | if (spiderpci_pci_setup_chip(bus->phb, regs)) | ||
| 157 | goto error; | ||
| 158 | |||
| 159 | return 0; | ||
| 160 | |||
| 161 | error: | ||
| 162 | kfree(priv); | ||
| 163 | bus->private = NULL; | ||
| 164 | |||
| 165 | if (regs) | ||
| 166 | iounmap(regs); | ||
| 167 | |||
| 168 | return -1; | ||
| 169 | } | ||
| 170 | |||
| 171 | struct ppc_pci_io spiderpci_ops = { | ||
| 172 | .readb = spiderpci_readb, | ||
| 173 | .readw = spiderpci_readw, | ||
| 174 | .readl = spiderpci_readl, | ||
| 175 | .readq = spiderpci_readq, | ||
| 176 | .readw_be = spiderpci_readw_be, | ||
| 177 | .readl_be = spiderpci_readl_be, | ||
| 178 | .readq_be = spiderpci_readq_be, | ||
| 179 | .readsb = spiderpci_readsb, | ||
| 180 | .readsw = spiderpci_readsw, | ||
| 181 | .readsl = spiderpci_readsl, | ||
| 182 | .memcpy_fromio = spiderpci_memcpy_fromio, | ||
| 183 | }; | ||
| 184 | |||
diff --git a/arch/powerpc/platforms/celleb/Kconfig b/arch/powerpc/platforms/celleb/Kconfig deleted file mode 100644 index 372891edcdd2..000000000000 --- a/arch/powerpc/platforms/celleb/Kconfig +++ /dev/null | |||
| @@ -1,12 +0,0 @@ | |||
| 1 | config PPC_CELLEB | ||
| 2 | bool "Toshiba's Cell Reference Set 'Celleb' Architecture" | ||
| 3 | depends on PPC_MULTIPLATFORM && PPC64 | ||
| 4 | select PPC_CELL | ||
| 5 | select PPC_CELL_NATIVE | ||
| 6 | select PPC_RTAS | ||
| 7 | select PPC_INDIRECT_IO | ||
| 8 | select PPC_OF_PLATFORM_PCI | ||
| 9 | select HAS_TXX9_SERIAL | ||
| 10 | select PPC_UDBG_BEAT | ||
| 11 | select USB_OHCI_BIG_ENDIAN_MMIO | ||
| 12 | select USB_EHCI_BIG_ENDIAN_MMIO | ||
diff --git a/arch/powerpc/platforms/celleb/Makefile b/arch/powerpc/platforms/celleb/Makefile deleted file mode 100644 index 889d43f715ea..000000000000 --- a/arch/powerpc/platforms/celleb/Makefile +++ /dev/null | |||
| @@ -1,9 +0,0 @@ | |||
| 1 | obj-y += interrupt.o iommu.o setup.o \ | ||
| 2 | htab.o beat.o hvCall.o pci.o \ | ||
| 3 | scc_epci.o scc_uhc.o \ | ||
| 4 | io-workarounds.o | ||
| 5 | |||
| 6 | obj-$(CONFIG_SMP) += smp.o | ||
| 7 | obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o | ||
| 8 | obj-$(CONFIG_SERIAL_TXX9) += scc_sio.o | ||
| 9 | obj-$(CONFIG_SPU_BASE) += spu_priv1.o | ||
diff --git a/arch/powerpc/platforms/celleb/io-workarounds.c b/arch/powerpc/platforms/celleb/io-workarounds.c deleted file mode 100644 index 423339be1bac..000000000000 --- a/arch/powerpc/platforms/celleb/io-workarounds.c +++ /dev/null | |||
| @@ -1,280 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Support for Celleb io workarounds | ||
| 3 | * | ||
| 4 | * (C) Copyright 2006-2007 TOSHIBA CORPORATION | ||
| 5 | * | ||
| 6 | * This file is based to arch/powerpc/platform/cell/io-workarounds.c | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License along | ||
| 19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #undef DEBUG | ||
| 24 | |||
| 25 | #include <linux/of.h> | ||
| 26 | #include <linux/of_device.h> | ||
| 27 | #include <linux/irq.h> | ||
| 28 | |||
| 29 | #include <asm/io.h> | ||
| 30 | #include <asm/prom.h> | ||
| 31 | #include <asm/machdep.h> | ||
| 32 | #include <asm/pci-bridge.h> | ||
| 33 | #include <asm/ppc-pci.h> | ||
| 34 | |||
| 35 | #include "pci.h" | ||
| 36 | |||
| 37 | #define MAX_CELLEB_PCI_BUS 4 | ||
| 38 | |||
| 39 | void *celleb_dummy_page_va; | ||
| 40 | |||
| 41 | static struct celleb_pci_bus { | ||
| 42 | struct pci_controller *phb; | ||
| 43 | void (*dummy_read)(struct pci_controller *); | ||
| 44 | } celleb_pci_busses[MAX_CELLEB_PCI_BUS]; | ||
| 45 | |||
| 46 | static int celleb_pci_count = 0; | ||
| 47 | |||
| 48 | static struct celleb_pci_bus *celleb_pci_find(unsigned long vaddr, | ||
| 49 | unsigned long paddr) | ||
| 50 | { | ||
| 51 | int i, j; | ||
| 52 | struct resource *res; | ||
| 53 | |||
| 54 | for (i = 0; i < celleb_pci_count; i++) { | ||
| 55 | struct celleb_pci_bus *bus = &celleb_pci_busses[i]; | ||
| 56 | struct pci_controller *phb = bus->phb; | ||
| 57 | if (paddr) | ||
| 58 | for (j = 0; j < 3; j++) { | ||
| 59 | res = &phb->mem_resources[j]; | ||
| 60 | if (paddr >= res->start && paddr <= res->end) | ||
| 61 | return bus; | ||
| 62 | } | ||
| 63 | res = &phb->io_resource; | ||
| 64 | if (vaddr && vaddr >= res->start && vaddr <= res->end) | ||
| 65 | return bus; | ||
| 66 | } | ||
| 67 | return NULL; | ||
| 68 | } | ||
| 69 | |||
| 70 | static void celleb_io_flush(const PCI_IO_ADDR addr) | ||
| 71 | { | ||
| 72 | struct celleb_pci_bus *bus; | ||
| 73 | int token; | ||
| 74 | |||
| 75 | token = PCI_GET_ADDR_TOKEN(addr); | ||
| 76 | |||
| 77 | if (token && token <= celleb_pci_count) | ||
| 78 | bus = &celleb_pci_busses[token - 1]; | ||
| 79 | else { | ||
| 80 | unsigned long vaddr, paddr; | ||
| 81 | pte_t *ptep; | ||
| 82 | |||
| 83 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); | ||
| 84 | if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END) | ||
| 85 | return; | ||
| 86 | |||
| 87 | ptep = find_linux_pte(init_mm.pgd, vaddr); | ||
| 88 | if (ptep == NULL) | ||
| 89 | paddr = 0; | ||
| 90 | else | ||
| 91 | paddr = pte_pfn(*ptep) << PAGE_SHIFT; | ||
| 92 | bus = celleb_pci_find(vaddr, paddr); | ||
| 93 | |||
| 94 | if (bus == NULL) | ||
| 95 | return; | ||
| 96 | } | ||
| 97 | |||
| 98 | if (bus->dummy_read) | ||
| 99 | bus->dummy_read(bus->phb); | ||
| 100 | } | ||
| 101 | |||
| 102 | static u8 celleb_readb(const PCI_IO_ADDR addr) | ||
| 103 | { | ||
| 104 | u8 val; | ||
| 105 | val = __do_readb(addr); | ||
| 106 | celleb_io_flush(addr); | ||
| 107 | return val; | ||
| 108 | } | ||
| 109 | |||
| 110 | static u16 celleb_readw(const PCI_IO_ADDR addr) | ||
| 111 | { | ||
| 112 | u16 val; | ||
| 113 | val = __do_readw(addr); | ||
| 114 | celleb_io_flush(addr); | ||
| 115 | return val; | ||
| 116 | } | ||
| 117 | |||
| 118 | static u32 celleb_readl(const PCI_IO_ADDR addr) | ||
| 119 | { | ||
| 120 | u32 val; | ||
| 121 | val = __do_readl(addr); | ||
| 122 | celleb_io_flush(addr); | ||
| 123 | return val; | ||
| 124 | } | ||
| 125 | |||
| 126 | static u64 celleb_readq(const PCI_IO_ADDR addr) | ||
| 127 | { | ||
| 128 | u64 val; | ||
| 129 | val = __do_readq(addr); | ||
| 130 | celleb_io_flush(addr); | ||
| 131 | return val; | ||
| 132 | } | ||
| 133 | |||
| 134 | static u16 celleb_readw_be(const PCI_IO_ADDR addr) | ||
| 135 | { | ||
| 136 | u16 val; | ||
| 137 | val = __do_readw_be(addr); | ||
| 138 | celleb_io_flush(addr); | ||
| 139 | return val; | ||
| 140 | } | ||
| 141 | |||
| 142 | static u32 celleb_readl_be(const PCI_IO_ADDR addr) | ||
| 143 | { | ||
| 144 | u32 val; | ||
| 145 | val = __do_readl_be(addr); | ||
| 146 | celleb_io_flush(addr); | ||
| 147 | return val; | ||
| 148 | } | ||
| 149 | |||
| 150 | static u64 celleb_readq_be(const PCI_IO_ADDR addr) | ||
| 151 | { | ||
| 152 | u64 val; | ||
| 153 | val = __do_readq_be(addr); | ||
| 154 | celleb_io_flush(addr); | ||
| 155 | return val; | ||
| 156 | } | ||
| 157 | |||
| 158 | static void celleb_readsb(const PCI_IO_ADDR addr, | ||
| 159 | void *buf, unsigned long count) | ||
| 160 | { | ||
| 161 | __do_readsb(addr, buf, count); | ||
| 162 | celleb_io_flush(addr); | ||
| 163 | } | ||
| 164 | |||
| 165 | static void celleb_readsw(const PCI_IO_ADDR addr, | ||
| 166 | void *buf, unsigned long count) | ||
| 167 | { | ||
| 168 | __do_readsw(addr, buf, count); | ||
| 169 | celleb_io_flush(addr); | ||
| 170 | } | ||
| 171 | |||
| 172 | static void celleb_readsl(const PCI_IO_ADDR addr, | ||
| 173 | void *buf, unsigned long count) | ||
| 174 | { | ||
| 175 | __do_readsl(addr, buf, count); | ||
| 176 | celleb_io_flush(addr); | ||
| 177 | } | ||
| 178 | |||
| 179 | static void celleb_memcpy_fromio(void *dest, | ||
| 180 | const PCI_IO_ADDR src, | ||
| 181 | unsigned long n) | ||
| 182 | { | ||
| 183 | __do_memcpy_fromio(dest, src, n); | ||
| 184 | celleb_io_flush(src); | ||
| 185 | } | ||
| 186 | |||
| 187 | static void __iomem *celleb_ioremap(unsigned long addr, | ||
| 188 | unsigned long size, | ||
| 189 | unsigned long flags) | ||
| 190 | { | ||
| 191 | struct celleb_pci_bus *bus; | ||
| 192 | void __iomem *res = __ioremap(addr, size, flags); | ||
| 193 | int busno; | ||
| 194 | |||
| 195 | bus = celleb_pci_find(0, addr); | ||
| 196 | if (bus != NULL) { | ||
| 197 | busno = bus - celleb_pci_busses; | ||
| 198 | PCI_SET_ADDR_TOKEN(res, busno + 1); | ||
| 199 | } | ||
| 200 | return res; | ||
| 201 | } | ||
| 202 | |||
| 203 | static void celleb_iounmap(volatile void __iomem *addr) | ||
| 204 | { | ||
| 205 | return __iounmap(PCI_FIX_ADDR(addr)); | ||
| 206 | } | ||
| 207 | |||
| 208 | static struct ppc_pci_io celleb_pci_io __initdata = { | ||
| 209 | .readb = celleb_readb, | ||
| 210 | .readw = celleb_readw, | ||
| 211 | .readl = celleb_readl, | ||
| 212 | .readq = celleb_readq, | ||
| 213 | .readw_be = celleb_readw_be, | ||
| 214 | .readl_be = celleb_readl_be, | ||
| 215 | .readq_be = celleb_readq_be, | ||
| 216 | .readsb = celleb_readsb, | ||
| 217 | .readsw = celleb_readsw, | ||
| 218 | .readsl = celleb_readsl, | ||
| 219 | .memcpy_fromio = celleb_memcpy_fromio, | ||
| 220 | }; | ||
| 221 | |||
| 222 | void __init celleb_pci_add_one(struct pci_controller *phb, | ||
| 223 | void (*dummy_read)(struct pci_controller *)) | ||
| 224 | { | ||
| 225 | struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count]; | ||
| 226 | struct device_node *np = phb->dn; | ||
| 227 | |||
| 228 | if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) { | ||
| 229 | printk(KERN_ERR "Too many pci bridges, workarounds" | ||
| 230 | " disabled for %s\n", np->full_name); | ||
| 231 | return; | ||
| 232 | } | ||
| 233 | |||
| 234 | celleb_pci_count++; | ||
| 235 | |||
| 236 | bus->phb = phb; | ||
| 237 | bus->dummy_read = dummy_read; | ||
| 238 | } | ||
| 239 | |||
| 240 | static struct of_device_id celleb_pci_workaround_match[] __initdata = { | ||
| 241 | { | ||
| 242 | .name = "pci-pseudo", | ||
| 243 | .data = fake_pci_workaround_init, | ||
| 244 | }, { | ||
| 245 | .name = "epci", | ||
| 246 | .data = epci_workaround_init, | ||
| 247 | }, { | ||
| 248 | }, | ||
| 249 | }; | ||
| 250 | |||
| 251 | int __init celleb_pci_workaround_init(void) | ||
| 252 | { | ||
| 253 | struct pci_controller *phb; | ||
| 254 | struct device_node *node; | ||
| 255 | const struct of_device_id *match; | ||
| 256 | void (*init_func)(struct pci_controller *); | ||
| 257 | |||
| 258 | celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 259 | if (!celleb_dummy_page_va) { | ||
| 260 | printk(KERN_ERR "Celleb: dummy read disabled. " | ||
| 261 | "Alloc celleb_dummy_page_va failed\n"); | ||
| 262 | return 1; | ||
| 263 | } | ||
| 264 | |||
| 265 | list_for_each_entry(phb, &hose_list, list_node) { | ||
| 266 | node = phb->dn; | ||
| 267 | match = of_match_node(celleb_pci_workaround_match, node); | ||
| 268 | |||
| 269 | if (match) { | ||
| 270 | init_func = match->data; | ||
| 271 | (*init_func)(phb); | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | ppc_pci_io = celleb_pci_io; | ||
| 276 | ppc_md.ioremap = celleb_ioremap; | ||
| 277 | ppc_md.iounmap = celleb_iounmap; | ||
| 278 | |||
| 279 | return 0; | ||
| 280 | } | ||
diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/platforms/iseries/exception.S index c775cd4b3d6e..8ff330d026ca 100644 --- a/arch/powerpc/platforms/iseries/exception.S +++ b/arch/powerpc/platforms/iseries/exception.S | |||
| @@ -59,8 +59,33 @@ system_reset_iSeries: | |||
| 59 | andc r4,r4,r5 | 59 | andc r4,r4,r5 |
| 60 | mtspr SPRN_CTRLT,r4 | 60 | mtspr SPRN_CTRLT,r4 |
| 61 | 61 | ||
| 62 | /* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */ | ||
| 63 | /* In the UP case we'll yeild() later, and we will not access the paca anyway */ | ||
| 64 | #ifdef CONFIG_SMP | ||
| 62 | 1: | 65 | 1: |
| 63 | HMT_LOW | 66 | HMT_LOW |
| 67 | LOAD_REG_IMMEDIATE(r23, __secondary_hold_spinloop) | ||
| 68 | ld r23,0(r23) | ||
| 69 | sync | ||
| 70 | LOAD_REG_IMMEDIATE(r3,current_set) | ||
| 71 | sldi r28,r24,3 /* get current_set[cpu#] */ | ||
| 72 | ldx r3,r3,r28 | ||
| 73 | addi r1,r3,THREAD_SIZE | ||
| 74 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
| 75 | |||
| 76 | cmpwi 0,r23,0 /* Keep poking the Hypervisor until */ | ||
| 77 | bne 2f /* we're released */ | ||
| 78 | /* Let the Hypervisor know we are alive */ | ||
| 79 | /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ | ||
| 80 | lis r3,0x8002 | ||
| 81 | rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */ | ||
| 82 | li r0,-1 /* r0=-1 indicates a Hypervisor call */ | ||
| 83 | sc /* Invoke the hypervisor via a system call */ | ||
| 84 | b 1b | ||
| 85 | #endif | ||
| 86 | |||
| 87 | 2: | ||
| 88 | HMT_LOW | ||
| 64 | #ifdef CONFIG_SMP | 89 | #ifdef CONFIG_SMP |
| 65 | lbz r23,PACAPROCSTART(r13) /* Test if this processor | 90 | lbz r23,PACAPROCSTART(r13) /* Test if this processor |
| 66 | * should start */ | 91 | * should start */ |
| @@ -91,7 +116,7 @@ iSeries_secondary_smp_loop: | |||
| 91 | li r0,-1 /* r0=-1 indicates a Hypervisor call */ | 116 | li r0,-1 /* r0=-1 indicates a Hypervisor call */ |
| 92 | sc /* Invoke the hypervisor via a system call */ | 117 | sc /* Invoke the hypervisor via a system call */ |
| 93 | mfspr r13,SPRN_SPRG3 /* Put r13 back ???? */ | 118 | mfspr r13,SPRN_SPRG3 /* Put r13 back ???? */ |
| 94 | b 1b /* If SMP not configured, secondaries | 119 | b 2b /* If SMP not configured, secondaries |
| 95 | * loop forever */ | 120 | * loop forever */ |
| 96 | 121 | ||
| 97 | /*** ISeries-LPAR interrupt handlers ***/ | 122 | /*** ISeries-LPAR interrupt handlers ***/ |
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c index c73379ec9141..1d201782d4e5 100644 --- a/arch/powerpc/platforms/ps3/os-area.c +++ b/arch/powerpc/platforms/ps3/os-area.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/syscalls.h> | 25 | #include <linux/syscalls.h> |
| 26 | #include <linux/ctype.h> | 26 | #include <linux/ctype.h> |
| 27 | #include <linux/lmb.h> | 27 | #include <linux/lmb.h> |
| 28 | #include <linux/of.h> | ||
| 28 | 29 | ||
| 29 | #include <asm/prom.h> | 30 | #include <asm/prom.h> |
| 30 | 31 | ||
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 306a9d07491d..07fe5b69b9e2 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
| @@ -34,3 +34,8 @@ config LPARCFG | |||
| 34 | help | 34 | help |
| 35 | Provide system capacity information via human readable | 35 | Provide system capacity information via human readable |
| 36 | <key word>=<value> pairs through a /proc/ppc64/lparcfg interface. | 36 | <key word>=<value> pairs through a /proc/ppc64/lparcfg interface. |
| 37 | |||
| 38 | config PPC_PSERIES_DEBUG | ||
| 39 | depends on PPC_PSERIES && PPC_EARLY_DEBUG | ||
| 40 | bool "Enable extra debug logging in platforms/pseries" | ||
| 41 | default y | ||
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index bdae04bb7a01..bd2593ed28dd 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
| @@ -2,6 +2,10 @@ ifeq ($(CONFIG_PPC64),y) | |||
| 2 | EXTRA_CFLAGS += -mno-minimal-toc | 2 | EXTRA_CFLAGS += -mno-minimal-toc |
| 3 | endif | 3 | endif |
| 4 | 4 | ||
| 5 | ifeq ($(CONFIG_PPC_PSERIES_DEBUG),y) | ||
| 6 | EXTRA_CFLAGS += -DDEBUG | ||
| 7 | endif | ||
| 8 | |||
| 5 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ | 9 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ |
| 6 | setup.o iommu.o ras.o rtasd.o \ | 10 | setup.o iommu.o ras.o rtasd.o \ |
| 7 | firmware.o power.o | 11 | firmware.o power.o |
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 550b2f7d2cc1..a3fd56b186e6 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
| @@ -39,7 +39,6 @@ | |||
| 39 | #include <asm/ppc-pci.h> | 39 | #include <asm/ppc-pci.h> |
| 40 | #include <asm/rtas.h> | 40 | #include <asm/rtas.h> |
| 41 | 41 | ||
| 42 | #undef DEBUG | ||
| 43 | 42 | ||
| 44 | /** Overview: | 43 | /** Overview: |
| 45 | * EEH, or "Extended Error Handling" is a PCI bridge technology for | 44 | * EEH, or "Extended Error Handling" is a PCI bridge technology for |
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c index 1e83fcd0df31..ce37040af870 100644 --- a/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/arch/powerpc/platforms/pseries/eeh_cache.c | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | #include <asm/pci-bridge.h> | 28 | #include <asm/pci-bridge.h> |
| 29 | #include <asm/ppc-pci.h> | 29 | #include <asm/ppc-pci.h> |
| 30 | 30 | ||
| 31 | #undef DEBUG | ||
| 32 | 31 | ||
| 33 | /** | 32 | /** |
| 34 | * The pci address cache subsystem. This subsystem places | 33 | * The pci address cache subsystem. This subsystem places |
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index b765b7c77b65..9d3a40f45974 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c | |||
| @@ -21,17 +21,11 @@ | |||
| 21 | * 2 of the License, or (at your option) any later version. | 21 | * 2 of the License, or (at your option) any later version. |
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #undef DEBUG | ||
| 25 | 24 | ||
| 26 | #include <asm/firmware.h> | 25 | #include <asm/firmware.h> |
| 27 | #include <asm/prom.h> | 26 | #include <asm/prom.h> |
| 28 | #include <asm/udbg.h> | 27 | #include <asm/udbg.h> |
| 29 | 28 | ||
| 30 | #ifdef DEBUG | ||
| 31 | #define DBG(fmt...) udbg_printf(fmt) | ||
| 32 | #else | ||
| 33 | #define DBG(fmt...) | ||
| 34 | #endif | ||
| 35 | 29 | ||
| 36 | typedef struct { | 30 | typedef struct { |
| 37 | unsigned long val; | 31 | unsigned long val; |
| @@ -72,7 +66,7 @@ void __init fw_feature_init(const char *hypertas, unsigned long len) | |||
| 72 | const char *s; | 66 | const char *s; |
| 73 | int i; | 67 | int i; |
| 74 | 68 | ||
| 75 | DBG(" -> fw_feature_init()\n"); | 69 | pr_debug(" -> fw_feature_init()\n"); |
| 76 | 70 | ||
| 77 | for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) { | 71 | for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) { |
| 78 | for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) { | 72 | for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) { |
| @@ -88,5 +82,5 @@ void __init fw_feature_init(const char *hypertas, unsigned long len) | |||
| 88 | } | 82 | } |
| 89 | } | 83 | } |
| 90 | 84 | ||
| 91 | DBG(" <- fw_feature_init()\n"); | 85 | pr_debug(" <- fw_feature_init()\n"); |
| 92 | } | 86 | } |
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index a65c76308201..176f1f39d2d5 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
| @@ -47,7 +47,6 @@ | |||
| 47 | 47 | ||
| 48 | #include "plpar_wrappers.h" | 48 | #include "plpar_wrappers.h" |
| 49 | 49 | ||
| 50 | #define DBG(fmt...) | ||
| 51 | 50 | ||
| 52 | static void tce_build_pSeries(struct iommu_table *tbl, long index, | 51 | static void tce_build_pSeries(struct iommu_table *tbl, long index, |
| 53 | long npages, unsigned long uaddr, | 52 | long npages, unsigned long uaddr, |
| @@ -322,7 +321,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus) | |||
| 322 | 321 | ||
| 323 | dn = pci_bus_to_OF_node(bus); | 322 | dn = pci_bus_to_OF_node(bus); |
| 324 | 323 | ||
| 325 | DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name); | 324 | pr_debug("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name); |
| 326 | 325 | ||
| 327 | if (bus->self) { | 326 | if (bus->self) { |
| 328 | /* This is not a root bus, any setup will be done for the | 327 | /* This is not a root bus, any setup will be done for the |
| @@ -347,7 +346,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus) | |||
| 347 | for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling) | 346 | for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling) |
| 348 | children++; | 347 | children++; |
| 349 | 348 | ||
| 350 | DBG("Children: %d\n", children); | 349 | pr_debug("Children: %d\n", children); |
| 351 | 350 | ||
| 352 | /* Calculate amount of DMA window per slot. Each window must be | 351 | /* Calculate amount of DMA window per slot. Each window must be |
| 353 | * a power of two (due to pci_alloc_consistent requirements). | 352 | * a power of two (due to pci_alloc_consistent requirements). |
| @@ -361,8 +360,8 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus) | |||
| 361 | 360 | ||
| 362 | while (pci->phb->dma_window_size * children > 0x80000000ul) | 361 | while (pci->phb->dma_window_size * children > 0x80000000ul) |
| 363 | pci->phb->dma_window_size >>= 1; | 362 | pci->phb->dma_window_size >>= 1; |
| 364 | DBG("No ISA/IDE, window size is 0x%lx\n", | 363 | pr_debug("No ISA/IDE, window size is 0x%lx\n", |
| 365 | pci->phb->dma_window_size); | 364 | pci->phb->dma_window_size); |
| 366 | pci->phb->dma_window_base_cur = 0; | 365 | pci->phb->dma_window_base_cur = 0; |
| 367 | 366 | ||
| 368 | return; | 367 | return; |
| @@ -387,8 +386,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus) | |||
| 387 | while (pci->phb->dma_window_size * children > 0x70000000ul) | 386 | while (pci->phb->dma_window_size * children > 0x70000000ul) |
| 388 | pci->phb->dma_window_size >>= 1; | 387 | pci->phb->dma_window_size >>= 1; |
| 389 | 388 | ||
| 390 | DBG("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size); | 389 | pr_debug("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size); |
| 391 | |||
| 392 | } | 390 | } |
| 393 | 391 | ||
| 394 | 392 | ||
| @@ -401,7 +399,8 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
| 401 | 399 | ||
| 402 | dn = pci_bus_to_OF_node(bus); | 400 | dn = pci_bus_to_OF_node(bus); |
| 403 | 401 | ||
| 404 | DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name); | 402 | pr_debug("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", |
| 403 | dn->full_name); | ||
| 405 | 404 | ||
| 406 | /* Find nearest ibm,dma-window, walking up the device tree */ | 405 | /* Find nearest ibm,dma-window, walking up the device tree */ |
| 407 | for (pdn = dn; pdn != NULL; pdn = pdn->parent) { | 406 | for (pdn = dn; pdn != NULL; pdn = pdn->parent) { |
| @@ -411,14 +410,14 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
| 411 | } | 410 | } |
| 412 | 411 | ||
| 413 | if (dma_window == NULL) { | 412 | if (dma_window == NULL) { |
| 414 | DBG(" no ibm,dma-window property !\n"); | 413 | pr_debug(" no ibm,dma-window property !\n"); |
| 415 | return; | 414 | return; |
| 416 | } | 415 | } |
| 417 | 416 | ||
| 418 | ppci = PCI_DN(pdn); | 417 | ppci = PCI_DN(pdn); |
| 419 | 418 | ||
| 420 | DBG(" parent is %s, iommu_table: 0x%p\n", | 419 | pr_debug(" parent is %s, iommu_table: 0x%p\n", |
| 421 | pdn->full_name, ppci->iommu_table); | 420 | pdn->full_name, ppci->iommu_table); |
| 422 | 421 | ||
| 423 | if (!ppci->iommu_table) { | 422 | if (!ppci->iommu_table) { |
| 424 | tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, | 423 | tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, |
| @@ -426,7 +425,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
| 426 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window, | 425 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window, |
| 427 | bus->number); | 426 | bus->number); |
| 428 | ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); | 427 | ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); |
| 429 | DBG(" created table: %p\n", ppci->iommu_table); | 428 | pr_debug(" created table: %p\n", ppci->iommu_table); |
| 430 | } | 429 | } |
| 431 | 430 | ||
| 432 | if (pdn != dn) | 431 | if (pdn != dn) |
| @@ -439,7 +438,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev) | |||
| 439 | struct device_node *dn; | 438 | struct device_node *dn; |
| 440 | struct iommu_table *tbl; | 439 | struct iommu_table *tbl; |
| 441 | 440 | ||
| 442 | DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev)); | 441 | pr_debug("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev)); |
| 443 | 442 | ||
| 444 | dn = dev->dev.archdata.of_node; | 443 | dn = dev->dev.archdata.of_node; |
| 445 | 444 | ||
| @@ -450,7 +449,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev) | |||
| 450 | if (!dev->bus->self) { | 449 | if (!dev->bus->self) { |
| 451 | struct pci_controller *phb = PCI_DN(dn)->phb; | 450 | struct pci_controller *phb = PCI_DN(dn)->phb; |
| 452 | 451 | ||
| 453 | DBG(" --> first child, no bridge. Allocating iommu table.\n"); | 452 | pr_debug(" --> first child, no bridge. Allocating iommu table.\n"); |
| 454 | tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, | 453 | tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, |
| 455 | phb->node); | 454 | phb->node); |
| 456 | iommu_table_setparms(phb, dn, tbl); | 455 | iommu_table_setparms(phb, dn, tbl); |
| @@ -480,7 +479,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
| 480 | const void *dma_window = NULL; | 479 | const void *dma_window = NULL; |
| 481 | struct pci_dn *pci; | 480 | struct pci_dn *pci; |
| 482 | 481 | ||
| 483 | DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev)); | 482 | pr_debug("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev)); |
| 484 | 483 | ||
| 485 | /* dev setup for LPAR is a little tricky, since the device tree might | 484 | /* dev setup for LPAR is a little tricky, since the device tree might |
| 486 | * contain the dma-window properties per-device and not neccesarily | 485 | * contain the dma-window properties per-device and not neccesarily |
| @@ -489,7 +488,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
| 489 | * already allocated. | 488 | * already allocated. |
| 490 | */ | 489 | */ |
| 491 | dn = pci_device_to_OF_node(dev); | 490 | dn = pci_device_to_OF_node(dev); |
| 492 | DBG(" node is %s\n", dn->full_name); | 491 | pr_debug(" node is %s\n", dn->full_name); |
| 493 | 492 | ||
| 494 | for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; | 493 | for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; |
| 495 | pdn = pdn->parent) { | 494 | pdn = pdn->parent) { |
| @@ -504,13 +503,13 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
| 504 | pci_name(dev), dn? dn->full_name : "<null>"); | 503 | pci_name(dev), dn? dn->full_name : "<null>"); |
| 505 | return; | 504 | return; |
| 506 | } | 505 | } |
| 507 | DBG(" parent is %s\n", pdn->full_name); | 506 | pr_debug(" parent is %s\n", pdn->full_name); |
| 508 | 507 | ||
| 509 | /* Check for parent == NULL so we don't try to setup the empty EADS | 508 | /* Check for parent == NULL so we don't try to setup the empty EADS |
| 510 | * slots on POWER4 machines. | 509 | * slots on POWER4 machines. |
| 511 | */ | 510 | */ |
| 512 | if (dma_window == NULL || pdn->parent == NULL) { | 511 | if (dma_window == NULL || pdn->parent == NULL) { |
| 513 | DBG(" no dma window for device, linking to parent\n"); | 512 | pr_debug(" no dma window for device, linking to parent\n"); |
| 514 | dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table; | 513 | dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table; |
| 515 | return; | 514 | return; |
| 516 | } | 515 | } |
| @@ -522,9 +521,9 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
| 522 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window, | 521 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window, |
| 523 | pci->phb->bus->number); | 522 | pci->phb->bus->number); |
| 524 | pci->iommu_table = iommu_init_table(tbl, pci->phb->node); | 523 | pci->iommu_table = iommu_init_table(tbl, pci->phb->node); |
| 525 | DBG(" created table: %p\n", pci->iommu_table); | 524 | pr_debug(" created table: %p\n", pci->iommu_table); |
| 526 | } else { | 525 | } else { |
| 527 | DBG(" found DMA window, table: %p\n", pci->iommu_table); | 526 | pr_debug(" found DMA window, table: %p\n", pci->iommu_table); |
| 528 | } | 527 | } |
| 529 | 528 | ||
| 530 | dev->dev.archdata.dma_data = pci->iommu_table; | 529 | dev->dev.archdata.dma_data = pci->iommu_table; |
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 9235c469449e..2cbaedb17f3e 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
| @@ -19,7 +19,8 @@ | |||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #undef DEBUG_LOW | 22 | /* Enables debugging of low-level hash table routines - careful! */ |
| 23 | #undef DEBUG | ||
| 23 | 24 | ||
| 24 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
| 25 | #include <linux/dma-mapping.h> | 26 | #include <linux/dma-mapping.h> |
| @@ -42,11 +43,6 @@ | |||
| 42 | #include "plpar_wrappers.h" | 43 | #include "plpar_wrappers.h" |
| 43 | #include "pseries.h" | 44 | #include "pseries.h" |
| 44 | 45 | ||
| 45 | #ifdef DEBUG_LOW | ||
| 46 | #define DBG_LOW(fmt...) do { udbg_printf(fmt); } while(0) | ||
| 47 | #else | ||
| 48 | #define DBG_LOW(fmt...) do { } while(0) | ||
| 49 | #endif | ||
| 50 | 46 | ||
| 51 | /* in hvCall.S */ | 47 | /* in hvCall.S */ |
| 52 | EXPORT_SYMBOL(plpar_hcall); | 48 | EXPORT_SYMBOL(plpar_hcall); |
| @@ -196,6 +192,8 @@ void __init udbg_init_debug_lpar(void) | |||
| 196 | udbg_putc = udbg_putcLP; | 192 | udbg_putc = udbg_putcLP; |
| 197 | udbg_getc = udbg_getcLP; | 193 | udbg_getc = udbg_getcLP; |
| 198 | udbg_getc_poll = udbg_getc_pollLP; | 194 | udbg_getc_poll = udbg_getc_pollLP; |
| 195 | |||
| 196 | register_early_udbg_console(); | ||
| 199 | } | 197 | } |
| 200 | 198 | ||
| 201 | /* returns 0 if couldn't find or use /chosen/stdout as console */ | 199 | /* returns 0 if couldn't find or use /chosen/stdout as console */ |
| @@ -288,15 +286,15 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, | |||
| 288 | unsigned long hpte_v, hpte_r; | 286 | unsigned long hpte_v, hpte_r; |
| 289 | 287 | ||
| 290 | if (!(vflags & HPTE_V_BOLTED)) | 288 | if (!(vflags & HPTE_V_BOLTED)) |
| 291 | DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " | 289 | pr_debug("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " |
| 292 | "rflags=%lx, vflags=%lx, psize=%d)\n", | 290 | "rflags=%lx, vflags=%lx, psize=%d)\n", |
| 293 | hpte_group, va, pa, rflags, vflags, psize); | 291 | hpte_group, va, pa, rflags, vflags, psize); |
| 294 | 292 | ||
| 295 | hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID; | 293 | hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID; |
| 296 | hpte_r = hpte_encode_r(pa, psize) | rflags; | 294 | hpte_r = hpte_encode_r(pa, psize) | rflags; |
| 297 | 295 | ||
| 298 | if (!(vflags & HPTE_V_BOLTED)) | 296 | if (!(vflags & HPTE_V_BOLTED)) |
| 299 | DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); | 297 | pr_debug(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); |
| 300 | 298 | ||
| 301 | /* Now fill in the actual HPTE */ | 299 | /* Now fill in the actual HPTE */ |
| 302 | /* Set CEC cookie to 0 */ | 300 | /* Set CEC cookie to 0 */ |
| @@ -313,7 +311,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, | |||
| 313 | lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot); | 311 | lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot); |
| 314 | if (unlikely(lpar_rc == H_PTEG_FULL)) { | 312 | if (unlikely(lpar_rc == H_PTEG_FULL)) { |
| 315 | if (!(vflags & HPTE_V_BOLTED)) | 313 | if (!(vflags & HPTE_V_BOLTED)) |
| 316 | DBG_LOW(" full\n"); | 314 | pr_debug(" full\n"); |
| 317 | return -1; | 315 | return -1; |
| 318 | } | 316 | } |
| 319 | 317 | ||
| @@ -324,11 +322,11 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, | |||
| 324 | */ | 322 | */ |
| 325 | if (unlikely(lpar_rc != H_SUCCESS)) { | 323 | if (unlikely(lpar_rc != H_SUCCESS)) { |
| 326 | if (!(vflags & HPTE_V_BOLTED)) | 324 | if (!(vflags & HPTE_V_BOLTED)) |
| 327 | DBG_LOW(" lpar err %d\n", lpar_rc); | 325 | pr_debug(" lpar err %lu\n", lpar_rc); |
| 328 | return -2; | 326 | return -2; |
| 329 | } | 327 | } |
| 330 | if (!(vflags & HPTE_V_BOLTED)) | 328 | if (!(vflags & HPTE_V_BOLTED)) |
| 331 | DBG_LOW(" -> slot: %d\n", slot & 7); | 329 | pr_debug(" -> slot: %lu\n", slot & 7); |
| 332 | 330 | ||
| 333 | /* Because of iSeries, we have to pass down the secondary | 331 | /* Because of iSeries, we have to pass down the secondary |
| 334 | * bucket bit here as well | 332 | * bucket bit here as well |
| @@ -420,17 +418,17 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, | |||
| 420 | 418 | ||
| 421 | want_v = hpte_encode_avpn(va, psize, ssize); | 419 | want_v = hpte_encode_avpn(va, psize, ssize); |
| 422 | 420 | ||
| 423 | DBG_LOW(" update: avpnv=%016lx, hash=%016lx, f=%x, psize: %d ... ", | 421 | pr_debug(" update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...", |
| 424 | want_v, slot, flags, psize); | 422 | want_v, slot, flags, psize); |
| 425 | 423 | ||
| 426 | lpar_rc = plpar_pte_protect(flags, slot, want_v); | 424 | lpar_rc = plpar_pte_protect(flags, slot, want_v); |
| 427 | 425 | ||
| 428 | if (lpar_rc == H_NOT_FOUND) { | 426 | if (lpar_rc == H_NOT_FOUND) { |
| 429 | DBG_LOW("not found !\n"); | 427 | pr_debug("not found !\n"); |
| 430 | return -1; | 428 | return -1; |
| 431 | } | 429 | } |
| 432 | 430 | ||
| 433 | DBG_LOW("ok\n"); | 431 | pr_debug("ok\n"); |
| 434 | 432 | ||
| 435 | BUG_ON(lpar_rc != H_SUCCESS); | 433 | BUG_ON(lpar_rc != H_SUCCESS); |
| 436 | 434 | ||
| @@ -505,8 +503,8 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | |||
| 505 | unsigned long lpar_rc; | 503 | unsigned long lpar_rc; |
| 506 | unsigned long dummy1, dummy2; | 504 | unsigned long dummy1, dummy2; |
| 507 | 505 | ||
| 508 | DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d", | 506 | pr_debug(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", |
| 509 | slot, va, psize, local); | 507 | slot, va, psize, local); |
| 510 | 508 | ||
| 511 | want_v = hpte_encode_avpn(va, psize, ssize); | 509 | want_v = hpte_encode_avpn(va, psize, ssize); |
| 512 | lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2); | 510 | lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2); |
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index a1ab25c7082f..2b548afd1003 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c | |||
| @@ -67,8 +67,6 @@ static int ras_check_exception_token; | |||
| 67 | static irqreturn_t ras_epow_interrupt(int irq, void *dev_id); | 67 | static irqreturn_t ras_epow_interrupt(int irq, void *dev_id); |
| 68 | static irqreturn_t ras_error_interrupt(int irq, void *dev_id); | 68 | static irqreturn_t ras_error_interrupt(int irq, void *dev_id); |
| 69 | 69 | ||
| 70 | /* #define DEBUG */ | ||
| 71 | |||
| 72 | 70 | ||
| 73 | static void request_ras_irqs(struct device_node *np, | 71 | static void request_ras_irqs(struct device_node *np, |
| 74 | irq_handler_t handler, | 72 | irq_handler_t handler, |
| @@ -237,7 +235,7 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id) | |||
| 237 | printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n", | 235 | printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n", |
| 238 | *((unsigned long *)&ras_log_buf), status); | 236 | *((unsigned long *)&ras_log_buf), status); |
| 239 | 237 | ||
| 240 | #ifndef DEBUG | 238 | #ifndef DEBUG_RTAS_POWER_OFF |
| 241 | /* Don't actually power off when debugging so we can test | 239 | /* Don't actually power off when debugging so we can test |
| 242 | * without actually failing while injecting errors. | 240 | * without actually failing while injecting errors. |
| 243 | * Error data will not be logged to syslog. | 241 | * Error data will not be logged to syslog. |
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index e3078ce41518..befadd4f9524 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c | |||
| @@ -29,11 +29,6 @@ | |||
| 29 | #include <asm/atomic.h> | 29 | #include <asm/atomic.h> |
| 30 | #include <asm/machdep.h> | 30 | #include <asm/machdep.h> |
| 31 | 31 | ||
| 32 | #if 0 | ||
| 33 | #define DEBUG(A...) printk(KERN_ERR A) | ||
| 34 | #else | ||
| 35 | #define DEBUG(A...) | ||
| 36 | #endif | ||
| 37 | 32 | ||
| 38 | static DEFINE_SPINLOCK(rtasd_log_lock); | 33 | static DEFINE_SPINLOCK(rtasd_log_lock); |
| 39 | 34 | ||
| @@ -198,7 +193,7 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) | |||
| 198 | unsigned long s; | 193 | unsigned long s; |
| 199 | int len = 0; | 194 | int len = 0; |
| 200 | 195 | ||
| 201 | DEBUG("logging event\n"); | 196 | pr_debug("rtasd: logging event\n"); |
| 202 | if (buf == NULL) | 197 | if (buf == NULL) |
| 203 | return; | 198 | return; |
| 204 | 199 | ||
| @@ -409,7 +404,8 @@ static int rtasd(void *unused) | |||
| 409 | daemonize("rtasd"); | 404 | daemonize("rtasd"); |
| 410 | 405 | ||
| 411 | printk(KERN_DEBUG "RTAS daemon started\n"); | 406 | printk(KERN_DEBUG "RTAS daemon started\n"); |
| 412 | DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate)); | 407 | pr_debug("rtasd: will sleep for %d milliseconds\n", |
| 408 | (30000 / rtas_event_scan_rate)); | ||
| 413 | 409 | ||
| 414 | /* See if we have any error stored in NVRAM */ | 410 | /* See if we have any error stored in NVRAM */ |
| 415 | memset(logdata, 0, rtas_error_log_max); | 411 | memset(logdata, 0, rtas_error_log_max); |
| @@ -428,9 +424,9 @@ static int rtasd(void *unused) | |||
| 428 | do_event_scan_all_cpus(1000); | 424 | do_event_scan_all_cpus(1000); |
| 429 | 425 | ||
| 430 | if (surveillance_timeout != -1) { | 426 | if (surveillance_timeout != -1) { |
| 431 | DEBUG("enabling surveillance\n"); | 427 | pr_debug("rtasd: enabling surveillance\n"); |
| 432 | enable_surveillance(surveillance_timeout); | 428 | enable_surveillance(surveillance_timeout); |
| 433 | DEBUG("surveillance enabled\n"); | 429 | pr_debug("rtasd: surveillance enabled\n"); |
| 434 | } | 430 | } |
| 435 | 431 | ||
| 436 | /* Delay should be at least one second since some | 432 | /* Delay should be at least one second since some |
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index e5b0ea870164..bec3803f0618 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c | |||
| @@ -38,9 +38,7 @@ | |||
| 38 | #define SCANLOG_HWERROR -1 | 38 | #define SCANLOG_HWERROR -1 |
| 39 | #define SCANLOG_CONTINUE 1 | 39 | #define SCANLOG_CONTINUE 1 |
| 40 | 40 | ||
| 41 | #define DEBUG(A...) do { if (scanlog_debug) printk(KERN_ERR "scanlog: " A); } while (0) | ||
| 42 | 41 | ||
| 43 | static int scanlog_debug; | ||
| 44 | static unsigned int ibm_scan_log_dump; /* RTAS token */ | 42 | static unsigned int ibm_scan_log_dump; /* RTAS token */ |
| 45 | static struct proc_dir_entry *proc_ppc64_scan_log_dump; /* The proc file */ | 43 | static struct proc_dir_entry *proc_ppc64_scan_log_dump; /* The proc file */ |
| 46 | 44 | ||
| @@ -86,14 +84,14 @@ static ssize_t scanlog_read(struct file *file, char __user *buf, | |||
| 86 | memcpy(data, rtas_data_buf, RTAS_DATA_BUF_SIZE); | 84 | memcpy(data, rtas_data_buf, RTAS_DATA_BUF_SIZE); |
| 87 | spin_unlock(&rtas_data_buf_lock); | 85 | spin_unlock(&rtas_data_buf_lock); |
| 88 | 86 | ||
| 89 | DEBUG("status=%d, data[0]=%x, data[1]=%x, data[2]=%x\n", | 87 | pr_debug("scanlog: status=%d, data[0]=%x, data[1]=%x, " \ |
| 90 | status, data[0], data[1], data[2]); | 88 | "data[2]=%x\n", status, data[0], data[1], data[2]); |
| 91 | switch (status) { | 89 | switch (status) { |
| 92 | case SCANLOG_COMPLETE: | 90 | case SCANLOG_COMPLETE: |
| 93 | DEBUG("hit eof\n"); | 91 | pr_debug("scanlog: hit eof\n"); |
| 94 | return 0; | 92 | return 0; |
| 95 | case SCANLOG_HWERROR: | 93 | case SCANLOG_HWERROR: |
| 96 | DEBUG("hardware error reading scan log data\n"); | 94 | pr_debug("scanlog: hardware error reading data\n"); |
| 97 | return -EIO; | 95 | return -EIO; |
| 98 | case SCANLOG_CONTINUE: | 96 | case SCANLOG_CONTINUE: |
| 99 | /* We may or may not have data yet */ | 97 | /* We may or may not have data yet */ |
| @@ -110,7 +108,8 @@ static ssize_t scanlog_read(struct file *file, char __user *buf, | |||
| 110 | /* Assume extended busy */ | 108 | /* Assume extended busy */ |
| 111 | wait_time = rtas_busy_delay_time(status); | 109 | wait_time = rtas_busy_delay_time(status); |
| 112 | if (!wait_time) { | 110 | if (!wait_time) { |
| 113 | printk(KERN_ERR "scanlog: unknown error from rtas: %d\n", status); | 111 | printk(KERN_ERR "scanlog: unknown error " \ |
| 112 | "from rtas: %d\n", status); | ||
| 114 | return -EIO; | 113 | return -EIO; |
| 115 | } | 114 | } |
| 116 | } | 115 | } |
| @@ -134,15 +133,9 @@ static ssize_t scanlog_write(struct file * file, const char __user * buf, | |||
| 134 | 133 | ||
| 135 | if (buf) { | 134 | if (buf) { |
| 136 | if (strncmp(stkbuf, "reset", 5) == 0) { | 135 | if (strncmp(stkbuf, "reset", 5) == 0) { |
| 137 | DEBUG("reset scanlog\n"); | 136 | pr_debug("scanlog: reset scanlog\n"); |
| 138 | status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, 0, 0); | 137 | status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, 0, 0); |
| 139 | DEBUG("rtas returns %d\n", status); | 138 | pr_debug("scanlog: rtas returns %d\n", status); |
| 140 | } else if (strncmp(stkbuf, "debugon", 7) == 0) { | ||
| 141 | printk(KERN_ERR "scanlog: debug on\n"); | ||
| 142 | scanlog_debug = 1; | ||
| 143 | } else if (strncmp(stkbuf, "debugoff", 8) == 0) { | ||
| 144 | printk(KERN_ERR "scanlog: debug off\n"); | ||
| 145 | scanlog_debug = 0; | ||
| 146 | } | 139 | } |
| 147 | } | 140 | } |
| 148 | return count; | 141 | return count; |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index f66aa9c3b135..f5d29f5b13c1 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
| @@ -16,8 +16,6 @@ | |||
| 16 | * bootup setup stuff.. | 16 | * bootup setup stuff.. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #undef DEBUG | ||
| 20 | |||
| 21 | #include <linux/cpu.h> | 19 | #include <linux/cpu.h> |
| 22 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
| 23 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
| @@ -70,11 +68,6 @@ | |||
| 70 | #include "plpar_wrappers.h" | 68 | #include "plpar_wrappers.h" |
| 71 | #include "pseries.h" | 69 | #include "pseries.h" |
| 72 | 70 | ||
| 73 | #ifdef DEBUG | ||
| 74 | #define DBG(fmt...) udbg_printf(fmt) | ||
| 75 | #else | ||
| 76 | #define DBG(fmt...) | ||
| 77 | #endif | ||
| 78 | 71 | ||
| 79 | int fwnmi_active; /* TRUE if an FWNMI handler is present */ | 72 | int fwnmi_active; /* TRUE if an FWNMI handler is present */ |
| 80 | 73 | ||
| @@ -326,7 +319,7 @@ static int pseries_set_xdabr(unsigned long dabr) | |||
| 326 | */ | 319 | */ |
| 327 | static void __init pSeries_init_early(void) | 320 | static void __init pSeries_init_early(void) |
| 328 | { | 321 | { |
| 329 | DBG(" -> pSeries_init_early()\n"); | 322 | pr_debug(" -> pSeries_init_early()\n"); |
| 330 | 323 | ||
| 331 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 324 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
| 332 | find_udbg_vterm(); | 325 | find_udbg_vterm(); |
| @@ -338,7 +331,7 @@ static void __init pSeries_init_early(void) | |||
| 338 | 331 | ||
| 339 | iommu_init_early_pSeries(); | 332 | iommu_init_early_pSeries(); |
| 340 | 333 | ||
| 341 | DBG(" <- pSeries_init_early()\n"); | 334 | pr_debug(" <- pSeries_init_early()\n"); |
| 342 | } | 335 | } |
| 343 | 336 | ||
| 344 | /* | 337 | /* |
| @@ -383,7 +376,7 @@ static int __init pSeries_probe(void) | |||
| 383 | of_flat_dt_is_compatible(root, "IBM,CBEA")) | 376 | of_flat_dt_is_compatible(root, "IBM,CBEA")) |
| 384 | return 0; | 377 | return 0; |
| 385 | 378 | ||
| 386 | DBG("pSeries detected, looking for LPAR capability...\n"); | 379 | pr_debug("pSeries detected, looking for LPAR capability...\n"); |
| 387 | 380 | ||
| 388 | /* Now try to figure out if we are running on LPAR */ | 381 | /* Now try to figure out if we are running on LPAR */ |
| 389 | of_scan_flat_dt(pSeries_probe_hypertas, NULL); | 382 | of_scan_flat_dt(pSeries_probe_hypertas, NULL); |
| @@ -393,8 +386,8 @@ static int __init pSeries_probe(void) | |||
| 393 | else | 386 | else |
| 394 | hpte_init_native(); | 387 | hpte_init_native(); |
| 395 | 388 | ||
| 396 | DBG("Machine is%s LPAR !\n", | 389 | pr_debug("Machine is%s LPAR !\n", |
| 397 | (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not"); | 390 | (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not"); |
| 398 | 391 | ||
| 399 | return 1; | 392 | return 1; |
| 400 | } | 393 | } |
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index ea4c65917a64..9d8f8c84ab89 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | * 2 of the License, or (at your option) any later version. | 12 | * 2 of the License, or (at your option) any later version. |
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #undef DEBUG | ||
| 16 | 15 | ||
| 17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| @@ -51,12 +50,6 @@ | |||
| 51 | #include "plpar_wrappers.h" | 50 | #include "plpar_wrappers.h" |
| 52 | #include "pseries.h" | 51 | #include "pseries.h" |
| 53 | 52 | ||
| 54 | #ifdef DEBUG | ||
| 55 | #include <asm/udbg.h> | ||
| 56 | #define DBG(fmt...) udbg_printf(fmt) | ||
| 57 | #else | ||
| 58 | #define DBG(fmt...) | ||
| 59 | #endif | ||
| 60 | 53 | ||
| 61 | /* | 54 | /* |
| 62 | * The primary thread of each non-boot processor is recorded here before | 55 | * The primary thread of each non-boot processor is recorded here before |
| @@ -231,7 +224,7 @@ static void __init smp_init_pseries(void) | |||
| 231 | { | 224 | { |
| 232 | int i; | 225 | int i; |
| 233 | 226 | ||
| 234 | DBG(" -> smp_init_pSeries()\n"); | 227 | pr_debug(" -> smp_init_pSeries()\n"); |
| 235 | 228 | ||
| 236 | /* Mark threads which are still spinning in hold loops. */ | 229 | /* Mark threads which are still spinning in hold loops. */ |
| 237 | if (cpu_has_feature(CPU_FTR_SMT)) { | 230 | if (cpu_has_feature(CPU_FTR_SMT)) { |
| @@ -255,7 +248,7 @@ static void __init smp_init_pseries(void) | |||
| 255 | smp_ops->take_timebase = pSeries_take_timebase; | 248 | smp_ops->take_timebase = pSeries_take_timebase; |
| 256 | } | 249 | } |
| 257 | 250 | ||
| 258 | DBG(" <- smp_init_pSeries()\n"); | 251 | pr_debug(" <- smp_init_pSeries()\n"); |
| 259 | } | 252 | } |
| 260 | 253 | ||
| 261 | #ifdef CONFIG_MPIC | 254 | #ifdef CONFIG_MPIC |
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 43df53c30aa0..ebebc28fe895 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #undef DEBUG | ||
| 13 | 12 | ||
| 14 | #include <linux/types.h> | 13 | #include <linux/types.h> |
| 15 | #include <linux/threads.h> | 14 | #include <linux/threads.h> |
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c index 047b31027fa6..41af1223e2a0 100644 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ b/arch/powerpc/sysdev/mv64x60_dev.c | |||
| @@ -338,15 +338,13 @@ static int __init mv64x60_i2c_device_setup(struct device_node *np, int id) | |||
| 338 | 338 | ||
| 339 | pdata.freq_m = 8; /* default */ | 339 | pdata.freq_m = 8; /* default */ |
| 340 | prop = of_get_property(np, "freq_m", NULL); | 340 | prop = of_get_property(np, "freq_m", NULL); |
| 341 | if (!prop) | 341 | if (prop) |
| 342 | return -ENODEV; | 342 | pdata.freq_m = *prop; |
| 343 | pdata.freq_m = *prop; | ||
| 344 | 343 | ||
| 345 | pdata.freq_m = 3; /* default */ | 344 | pdata.freq_m = 3; /* default */ |
| 346 | prop = of_get_property(np, "freq_n", NULL); | 345 | prop = of_get_property(np, "freq_n", NULL); |
| 347 | if (!prop) | 346 | if (prop) |
| 348 | return -ENODEV; | 347 | pdata.freq_n = *prop; |
| 349 | pdata.freq_n = *prop; | ||
| 350 | 348 | ||
| 351 | pdata.timeout = 1000; /* default: 1 second */ | 349 | pdata.timeout = 1000; /* default: 1 second */ |
| 352 | 350 | ||
| @@ -433,9 +431,13 @@ static int __init mv64x60_device_setup(void) | |||
| 433 | int err; | 431 | int err; |
| 434 | 432 | ||
| 435 | id = 0; | 433 | id = 0; |
| 436 | for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") | 434 | for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") { |
| 437 | if ((err = mv64x60_mpsc_device_setup(np, id++))) | 435 | err = mv64x60_mpsc_device_setup(np, id++); |
| 438 | goto error; | 436 | if (err) |
| 437 | printk(KERN_ERR "Failed to initialize MV64x60 " | ||
| 438 | "serial device %s: error %d.\n", | ||
| 439 | np->full_name, err); | ||
| 440 | } | ||
| 439 | 441 | ||
| 440 | id = 0; | 442 | id = 0; |
| 441 | id2 = 0; | 443 | id2 = 0; |
| @@ -443,38 +445,44 @@ static int __init mv64x60_device_setup(void) | |||
| 443 | pdev = mv64x60_eth_register_shared_pdev(np, id++); | 445 | pdev = mv64x60_eth_register_shared_pdev(np, id++); |
| 444 | if (IS_ERR(pdev)) { | 446 | if (IS_ERR(pdev)) { |
| 445 | err = PTR_ERR(pdev); | 447 | err = PTR_ERR(pdev); |
| 446 | goto error; | 448 | printk(KERN_ERR "Failed to initialize MV64x60 " |
| 449 | "network block %s: error %d.\n", | ||
| 450 | np->full_name, err); | ||
| 451 | continue; | ||
| 447 | } | 452 | } |
| 448 | for_each_child_of_node(np, np2) { | 453 | for_each_child_of_node(np, np2) { |
| 449 | if (!of_device_is_compatible(np2, | 454 | if (!of_device_is_compatible(np2, |
| 450 | "marvell,mv64360-eth")) | 455 | "marvell,mv64360-eth")) |
| 451 | continue; | 456 | continue; |
| 452 | err = mv64x60_eth_device_setup(np2, id2++, pdev); | 457 | err = mv64x60_eth_device_setup(np2, id2++, pdev); |
| 453 | if (err) { | 458 | if (err) |
| 454 | of_node_put(np2); | 459 | printk(KERN_ERR "Failed to initialize " |
| 455 | goto error; | 460 | "MV64x60 network device %s: " |
| 456 | } | 461 | "error %d.\n", |
| 462 | np2->full_name, err); | ||
| 457 | } | 463 | } |
| 458 | } | 464 | } |
| 459 | 465 | ||
| 460 | id = 0; | 466 | id = 0; |
| 461 | for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c") | 467 | for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c") { |
| 462 | if ((err = mv64x60_i2c_device_setup(np, id++))) | 468 | err = mv64x60_i2c_device_setup(np, id++); |
| 463 | goto error; | 469 | if (err) |
| 470 | printk(KERN_ERR "Failed to initialize MV64x60 I2C " | ||
| 471 | "bus %s: error %d.\n", | ||
| 472 | np->full_name, err); | ||
| 473 | } | ||
| 464 | 474 | ||
| 465 | /* support up to one watchdog timer */ | 475 | /* support up to one watchdog timer */ |
| 466 | np = of_find_compatible_node(np, NULL, "marvell,mv64360-wdt"); | 476 | np = of_find_compatible_node(np, NULL, "marvell,mv64360-wdt"); |
| 467 | if (np) { | 477 | if (np) { |
| 468 | if ((err = mv64x60_wdt_device_setup(np, id))) | 478 | if ((err = mv64x60_wdt_device_setup(np, id))) |
| 469 | goto error; | 479 | printk(KERN_ERR "Failed to initialize MV64x60 " |
| 480 | "Watchdog %s: error %d.\n", | ||
| 481 | np->full_name, err); | ||
| 470 | of_node_put(np); | 482 | of_node_put(np); |
| 471 | } | 483 | } |
| 472 | 484 | ||
| 473 | return 0; | 485 | return 0; |
| 474 | |||
| 475 | error: | ||
| 476 | of_node_put(np); | ||
| 477 | return err; | ||
| 478 | } | 486 | } |
| 479 | arch_initcall(mv64x60_device_setup); | 487 | arch_initcall(mv64x60_device_setup); |
| 480 | 488 | ||
diff --git a/arch/powerpc/sysdev/mv64x60_udbg.c b/arch/powerpc/sysdev/mv64x60_udbg.c index ccdb3b0418fc..2792dc8b038c 100644 --- a/arch/powerpc/sysdev/mv64x60_udbg.c +++ b/arch/powerpc/sysdev/mv64x60_udbg.c | |||
| @@ -94,7 +94,7 @@ static void mv64x60_udbg_init(void) | |||
| 94 | if (!np) | 94 | if (!np) |
| 95 | return; | 95 | return; |
| 96 | 96 | ||
| 97 | block_index = of_get_property(np, "block-index", NULL); | 97 | block_index = of_get_property(np, "cell-index", NULL); |
| 98 | if (!block_index) | 98 | if (!block_index) |
| 99 | goto error; | 99 | goto error; |
| 100 | 100 | ||
