diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-07-21 23:16:41 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-07-21 23:16:41 -0400 |
commit | 4b575f3e8aba07688fc48025efde41036e5d5eee (patch) | |
tree | 4bbccce83e80af179500be45f9e8080315f5e32e | |
parent | f7723f0eaf53d51ee54374116b25ac33e0be8542 (diff) | |
parent | a8e616b9a41212655042f59c969f30bb7de1ec73 (diff) |
Merge remote-tracking branch 'jwb/next' into next
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | arch/powerpc/Kconfig | 2 | ||||
-rw-r--r-- | arch/powerpc/boot/dts/taishan.dts | 4 | ||||
-rw-r--r-- | arch/powerpc/boot/treeboot-iss4xx.c | 23 | ||||
-rw-r--r-- | arch/powerpc/configs/44x/iss476-smp_defconfig | 6 | ||||
-rw-r--r-- | arch/powerpc/include/asm/mmu.h | 7 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_44x.S | 42 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_32.c | 2 | ||||
-rw-r--r-- | arch/powerpc/mm/44x_mmu.c | 13 | ||||
-rw-r--r-- | arch/powerpc/mm/tlb_hash32.c | 4 | ||||
-rw-r--r-- | arch/powerpc/mm/tlb_nohash.c | 19 | ||||
-rw-r--r-- | arch/powerpc/sysdev/ppc4xx_pci.c | 147 |
12 files changed, 186 insertions, 85 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 2b3969135b39..d586f2bb3dc7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3876,7 +3876,7 @@ F: arch/powerpc/platforms/512x/ | |||
3876 | F: arch/powerpc/platforms/52xx/ | 3876 | F: arch/powerpc/platforms/52xx/ |
3877 | 3877 | ||
3878 | LINUX FOR POWERPC EMBEDDED PPC4XX | 3878 | LINUX FOR POWERPC EMBEDDED PPC4XX |
3879 | M: Josh Boyer <jwboyer@linux.vnet.ibm.com> | 3879 | M: Josh Boyer <jwboyer@gmail.com> |
3880 | M: Matt Porter <mporter@kernel.crashing.org> | 3880 | M: Matt Porter <mporter@kernel.crashing.org> |
3881 | W: http://www.penguinppc.org/ | 3881 | W: http://www.penguinppc.org/ |
3882 | L: linuxppc-dev@lists.ozlabs.org | 3882 | L: linuxppc-dev@lists.ozlabs.org |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c15f2e61e4fd..f8e578be5806 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -842,7 +842,7 @@ config LOWMEM_CAM_NUM | |||
842 | 842 | ||
843 | config RELOCATABLE | 843 | config RELOCATABLE |
844 | bool "Build a relocatable kernel (EXPERIMENTAL)" | 844 | bool "Build a relocatable kernel (EXPERIMENTAL)" |
845 | depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE | 845 | depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && (FSL_BOOKE || PPC_47x) |
846 | help | 846 | help |
847 | This builds a kernel image that is capable of running at the | 847 | This builds a kernel image that is capable of running at the |
848 | location the kernel is loaded at (some alignment restrictions may | 848 | location the kernel is loaded at (some alignment restrictions may |
diff --git a/arch/powerpc/boot/dts/taishan.dts b/arch/powerpc/boot/dts/taishan.dts index 058438f9629b..1657ad0bf8a6 100644 --- a/arch/powerpc/boot/dts/taishan.dts +++ b/arch/powerpc/boot/dts/taishan.dts | |||
@@ -337,7 +337,7 @@ | |||
337 | rx-fifo-size = <4096>; | 337 | rx-fifo-size = <4096>; |
338 | tx-fifo-size = <2048>; | 338 | tx-fifo-size = <2048>; |
339 | phy-mode = "rgmii"; | 339 | phy-mode = "rgmii"; |
340 | phy-map = <0x00000001>; | 340 | phy-address = <1>; |
341 | rgmii-device = <&RGMII0>; | 341 | rgmii-device = <&RGMII0>; |
342 | rgmii-channel = <0>; | 342 | rgmii-channel = <0>; |
343 | zmii-device = <&ZMII0>; | 343 | zmii-device = <&ZMII0>; |
@@ -361,7 +361,7 @@ | |||
361 | rx-fifo-size = <4096>; | 361 | rx-fifo-size = <4096>; |
362 | tx-fifo-size = <2048>; | 362 | tx-fifo-size = <2048>; |
363 | phy-mode = "rgmii"; | 363 | phy-mode = "rgmii"; |
364 | phy-map = <0x00000003>; | 364 | phy-address = <3>; |
365 | rgmii-device = <&RGMII0>; | 365 | rgmii-device = <&RGMII0>; |
366 | rgmii-channel = <1>; | 366 | rgmii-channel = <1>; |
367 | zmii-device = <&ZMII0>; | 367 | zmii-device = <&ZMII0>; |
diff --git a/arch/powerpc/boot/treeboot-iss4xx.c b/arch/powerpc/boot/treeboot-iss4xx.c index fcc44952874e..329e710feda2 100644 --- a/arch/powerpc/boot/treeboot-iss4xx.c +++ b/arch/powerpc/boot/treeboot-iss4xx.c | |||
@@ -34,9 +34,29 @@ | |||
34 | 34 | ||
35 | BSS_STACK(4096); | 35 | BSS_STACK(4096); |
36 | 36 | ||
37 | static u32 ibm4xx_memstart; | ||
38 | |||
37 | static void iss_4xx_fixups(void) | 39 | static void iss_4xx_fixups(void) |
38 | { | 40 | { |
39 | ibm4xx_sdram_fixup_memsize(); | 41 | void *memory; |
42 | u32 reg[3]; | ||
43 | |||
44 | memory = finddevice("/memory"); | ||
45 | if (!memory) | ||
46 | fatal("Can't find memory node\n"); | ||
47 | /* This assumes #address-cells = 2, #size-cells =1 and that */ | ||
48 | getprop(memory, "reg", reg, sizeof(reg)); | ||
49 | if (reg[2]) | ||
50 | /* If the device tree specifies the memory range, use it */ | ||
51 | ibm4xx_memstart = reg[1]; | ||
52 | else | ||
53 | /* othersize, read it from the SDRAM controller */ | ||
54 | ibm4xx_sdram_fixup_memsize(); | ||
55 | } | ||
56 | |||
57 | static void *iss_4xx_vmlinux_alloc(unsigned long size) | ||
58 | { | ||
59 | return (void *)ibm4xx_memstart; | ||
40 | } | 60 | } |
41 | 61 | ||
42 | #define SPRN_PIR 0x11E /* Processor Indentification Register */ | 62 | #define SPRN_PIR 0x11E /* Processor Indentification Register */ |
@@ -48,6 +68,7 @@ void platform_init(void) | |||
48 | 68 | ||
49 | simple_alloc_init(_end, avail_ram, 128, 64); | 69 | simple_alloc_init(_end, avail_ram, 128, 64); |
50 | platform_ops.fixups = iss_4xx_fixups; | 70 | platform_ops.fixups = iss_4xx_fixups; |
71 | platform_ops.vmlinux_alloc = iss_4xx_vmlinux_alloc; | ||
51 | platform_ops.exit = ibm44x_dbcr_reset; | 72 | platform_ops.exit = ibm44x_dbcr_reset; |
52 | pir_reg = mfspr(SPRN_PIR); | 73 | pir_reg = mfspr(SPRN_PIR); |
53 | fdt_set_boot_cpuid_phys(_dtb_start, pir_reg); | 74 | fdt_set_boot_cpuid_phys(_dtb_start, pir_reg); |
diff --git a/arch/powerpc/configs/44x/iss476-smp_defconfig b/arch/powerpc/configs/44x/iss476-smp_defconfig index 92f863ac8443..a6eb6ad05b2d 100644 --- a/arch/powerpc/configs/44x/iss476-smp_defconfig +++ b/arch/powerpc/configs/44x/iss476-smp_defconfig | |||
@@ -3,8 +3,8 @@ CONFIG_SMP=y | |||
3 | CONFIG_EXPERIMENTAL=y | 3 | CONFIG_EXPERIMENTAL=y |
4 | CONFIG_SYSVIPC=y | 4 | CONFIG_SYSVIPC=y |
5 | CONFIG_POSIX_MQUEUE=y | 5 | CONFIG_POSIX_MQUEUE=y |
6 | CONFIG_SPARSE_IRQ=y | ||
6 | CONFIG_LOG_BUF_SHIFT=14 | 7 | CONFIG_LOG_BUF_SHIFT=14 |
7 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
8 | CONFIG_BLK_DEV_INITRD=y | 8 | CONFIG_BLK_DEV_INITRD=y |
9 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | 9 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set |
10 | CONFIG_EXPERT=y | 10 | CONFIG_EXPERT=y |
@@ -21,10 +21,11 @@ CONFIG_ISS4xx=y | |||
21 | CONFIG_HZ_100=y | 21 | CONFIG_HZ_100=y |
22 | CONFIG_MATH_EMULATION=y | 22 | CONFIG_MATH_EMULATION=y |
23 | CONFIG_IRQ_ALL_CPUS=y | 23 | CONFIG_IRQ_ALL_CPUS=y |
24 | CONFIG_SPARSE_IRQ=y | ||
25 | CONFIG_CMDLINE_BOOL=y | 24 | CONFIG_CMDLINE_BOOL=y |
26 | CONFIG_CMDLINE="root=/dev/issblk0" | 25 | CONFIG_CMDLINE="root=/dev/issblk0" |
27 | # CONFIG_PCI is not set | 26 | # CONFIG_PCI is not set |
27 | CONFIG_ADVANCED_OPTIONS=y | ||
28 | CONFIG_RELOCATABLE=y | ||
28 | CONFIG_NET=y | 29 | CONFIG_NET=y |
29 | CONFIG_PACKET=y | 30 | CONFIG_PACKET=y |
30 | CONFIG_UNIX=y | 31 | CONFIG_UNIX=y |
@@ -67,7 +68,6 @@ CONFIG_EXT3_FS=y | |||
67 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | 68 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set |
68 | CONFIG_EXT3_FS_POSIX_ACL=y | 69 | CONFIG_EXT3_FS_POSIX_ACL=y |
69 | CONFIG_EXT3_FS_SECURITY=y | 70 | CONFIG_EXT3_FS_SECURITY=y |
70 | CONFIG_INOTIFY=y | ||
71 | CONFIG_PROC_KCORE=y | 71 | CONFIG_PROC_KCORE=y |
72 | CONFIG_TMPFS=y | 72 | CONFIG_TMPFS=y |
73 | CONFIG_CRAMFS=y | 73 | CONFIG_CRAMFS=y |
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index b427a55ce2ab..698b30638681 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h | |||
@@ -125,9 +125,14 @@ static inline int mmu_has_feature(unsigned long feature) | |||
125 | return (cur_cpu_spec->mmu_features & feature); | 125 | return (cur_cpu_spec->mmu_features & feature); |
126 | } | 126 | } |
127 | 127 | ||
128 | static inline void mmu_clear_feature(unsigned long feature) | ||
129 | { | ||
130 | cur_cpu_spec->mmu_features &= ~feature; | ||
131 | } | ||
132 | |||
128 | extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup; | 133 | extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup; |
129 | 134 | ||
130 | /* MMU initialization (64-bit only fo now) */ | 135 | /* MMU initialization */ |
131 | extern void early_init_mmu(void); | 136 | extern void early_init_mmu(void); |
132 | extern void early_init_mmu_secondary(void); | 137 | extern void early_init_mmu_secondary(void); |
133 | 138 | ||
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index 5e12b741ba5f..f8e971ba94f5 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S | |||
@@ -93,6 +93,30 @@ _ENTRY(_start); | |||
93 | 93 | ||
94 | bl early_init | 94 | bl early_init |
95 | 95 | ||
96 | #ifdef CONFIG_RELOCATABLE | ||
97 | /* | ||
98 | * r25 will contain RPN/ERPN for the start address of memory | ||
99 | * | ||
100 | * Add the difference between KERNELBASE and PAGE_OFFSET to the | ||
101 | * start of physical memory to get kernstart_addr. | ||
102 | */ | ||
103 | lis r3,kernstart_addr@ha | ||
104 | la r3,kernstart_addr@l(r3) | ||
105 | |||
106 | lis r4,KERNELBASE@h | ||
107 | ori r4,r4,KERNELBASE@l | ||
108 | lis r5,PAGE_OFFSET@h | ||
109 | ori r5,r5,PAGE_OFFSET@l | ||
110 | subf r4,r5,r4 | ||
111 | |||
112 | rlwinm r6,r25,0,28,31 /* ERPN */ | ||
113 | rlwinm r7,r25,0,0,3 /* RPN - assuming 256 MB page size */ | ||
114 | add r7,r7,r4 | ||
115 | |||
116 | stw r6,0(r3) | ||
117 | stw r7,4(r3) | ||
118 | #endif | ||
119 | |||
96 | /* | 120 | /* |
97 | * Decide what sort of machine this is and initialize the MMU. | 121 | * Decide what sort of machine this is and initialize the MMU. |
98 | */ | 122 | */ |
@@ -1001,9 +1025,6 @@ clear_utlb_entry: | |||
1001 | lis r3,PAGE_OFFSET@h | 1025 | lis r3,PAGE_OFFSET@h |
1002 | ori r3,r3,PAGE_OFFSET@l | 1026 | ori r3,r3,PAGE_OFFSET@l |
1003 | 1027 | ||
1004 | /* Kernel is at the base of RAM */ | ||
1005 | li r4, 0 /* Load the kernel physical address */ | ||
1006 | |||
1007 | /* Load the kernel PID = 0 */ | 1028 | /* Load the kernel PID = 0 */ |
1008 | li r0,0 | 1029 | li r0,0 |
1009 | mtspr SPRN_PID,r0 | 1030 | mtspr SPRN_PID,r0 |
@@ -1013,9 +1034,8 @@ clear_utlb_entry: | |||
1013 | clrrwi r3,r3,12 /* Mask off the effective page number */ | 1034 | clrrwi r3,r3,12 /* Mask off the effective page number */ |
1014 | ori r3,r3,PPC47x_TLB0_VALID | PPC47x_TLB0_256M | 1035 | ori r3,r3,PPC47x_TLB0_VALID | PPC47x_TLB0_256M |
1015 | 1036 | ||
1016 | /* Word 1 */ | 1037 | /* Word 1 - use r25. RPN is the same as the original entry */ |
1017 | clrrwi r4,r4,12 /* Mask off the real page number */ | 1038 | |
1018 | /* ERPN is 0 for first 4GB page */ | ||
1019 | /* Word 2 */ | 1039 | /* Word 2 */ |
1020 | li r5,0 | 1040 | li r5,0 |
1021 | ori r5,r5,PPC47x_TLB2_S_RWX | 1041 | ori r5,r5,PPC47x_TLB2_S_RWX |
@@ -1026,7 +1046,7 @@ clear_utlb_entry: | |||
1026 | /* We write to way 0 and bolted 0 */ | 1046 | /* We write to way 0 and bolted 0 */ |
1027 | lis r0,0x8800 | 1047 | lis r0,0x8800 |
1028 | tlbwe r3,r0,0 | 1048 | tlbwe r3,r0,0 |
1029 | tlbwe r4,r0,1 | 1049 | tlbwe r25,r0,1 |
1030 | tlbwe r5,r0,2 | 1050 | tlbwe r5,r0,2 |
1031 | 1051 | ||
1032 | /* | 1052 | /* |
@@ -1124,7 +1144,13 @@ head_start_common: | |||
1124 | lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */ | 1144 | lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */ |
1125 | mtspr SPRN_IVPR,r4 | 1145 | mtspr SPRN_IVPR,r4 |
1126 | 1146 | ||
1127 | addis r22,r22,KERNELBASE@h | 1147 | /* |
1148 | * If the kernel was loaded at a non-zero 256 MB page, we need to | ||
1149 | * mask off the most significant 4 bits to get the relative address | ||
1150 | * from the start of physical memory | ||
1151 | */ | ||
1152 | rlwinm r22,r22,0,4,31 | ||
1153 | addis r22,r22,PAGE_OFFSET@h | ||
1128 | mtlr r22 | 1154 | mtlr r22 |
1129 | isync | 1155 | isync |
1130 | blr | 1156 | blr |
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 3dffce673c1f..209135af0a40 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -127,6 +127,8 @@ notrace void __init machine_init(unsigned long dt_ptr) | |||
127 | /* Do some early initialization based on the flat device tree */ | 127 | /* Do some early initialization based on the flat device tree */ |
128 | early_init_devtree(__va(dt_ptr)); | 128 | early_init_devtree(__va(dt_ptr)); |
129 | 129 | ||
130 | early_init_mmu(); | ||
131 | |||
130 | probe_machine(); | 132 | probe_machine(); |
131 | 133 | ||
132 | setup_kdump_trampoline(); | 134 | setup_kdump_trampoline(); |
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c index 024acab588fd..f60e006d90c3 100644 --- a/arch/powerpc/mm/44x_mmu.c +++ b/arch/powerpc/mm/44x_mmu.c | |||
@@ -186,10 +186,11 @@ void __init MMU_init_hw(void) | |||
186 | unsigned long __init mmu_mapin_ram(unsigned long top) | 186 | unsigned long __init mmu_mapin_ram(unsigned long top) |
187 | { | 187 | { |
188 | unsigned long addr; | 188 | unsigned long addr; |
189 | unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1); | ||
189 | 190 | ||
190 | /* Pin in enough TLBs to cover any lowmem not covered by the | 191 | /* Pin in enough TLBs to cover any lowmem not covered by the |
191 | * initial 256M mapping established in head_44x.S */ | 192 | * initial 256M mapping established in head_44x.S */ |
192 | for (addr = PPC_PIN_SIZE; addr < lowmem_end_addr; | 193 | for (addr = memstart + PPC_PIN_SIZE; addr < lowmem_end_addr; |
193 | addr += PPC_PIN_SIZE) { | 194 | addr += PPC_PIN_SIZE) { |
194 | if (mmu_has_feature(MMU_FTR_TYPE_47x)) | 195 | if (mmu_has_feature(MMU_FTR_TYPE_47x)) |
195 | ppc47x_pin_tlb(addr + PAGE_OFFSET, addr); | 196 | ppc47x_pin_tlb(addr + PAGE_OFFSET, addr); |
@@ -218,19 +219,25 @@ unsigned long __init mmu_mapin_ram(unsigned long top) | |||
218 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, | 219 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, |
219 | phys_addr_t first_memblock_size) | 220 | phys_addr_t first_memblock_size) |
220 | { | 221 | { |
222 | u64 size; | ||
223 | |||
224 | #ifndef CONFIG_RELOCATABLE | ||
221 | /* We don't currently support the first MEMBLOCK not mapping 0 | 225 | /* We don't currently support the first MEMBLOCK not mapping 0 |
222 | * physical on those processors | 226 | * physical on those processors |
223 | */ | 227 | */ |
224 | BUG_ON(first_memblock_base != 0); | 228 | BUG_ON(first_memblock_base != 0); |
229 | #endif | ||
225 | 230 | ||
226 | /* 44x has a 256M TLB entry pinned at boot */ | 231 | /* 44x has a 256M TLB entry pinned at boot */ |
227 | memblock_set_current_limit(min_t(u64, first_memblock_size, PPC_PIN_SIZE)); | 232 | size = (min_t(u64, first_memblock_size, PPC_PIN_SIZE)); |
233 | memblock_set_current_limit(first_memblock_base + size); | ||
228 | } | 234 | } |
229 | 235 | ||
230 | #ifdef CONFIG_SMP | 236 | #ifdef CONFIG_SMP |
231 | void __cpuinit mmu_init_secondary(int cpu) | 237 | void __cpuinit mmu_init_secondary(int cpu) |
232 | { | 238 | { |
233 | unsigned long addr; | 239 | unsigned long addr; |
240 | unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1); | ||
234 | 241 | ||
235 | /* Pin in enough TLBs to cover any lowmem not covered by the | 242 | /* Pin in enough TLBs to cover any lowmem not covered by the |
236 | * initial 256M mapping established in head_44x.S | 243 | * initial 256M mapping established in head_44x.S |
@@ -241,7 +248,7 @@ void __cpuinit mmu_init_secondary(int cpu) | |||
241 | * stack. current (r2) isn't initialized, smp_processor_id() | 248 | * stack. current (r2) isn't initialized, smp_processor_id() |
242 | * will not work, current thread info isn't accessible, ... | 249 | * will not work, current thread info isn't accessible, ... |
243 | */ | 250 | */ |
244 | for (addr = PPC_PIN_SIZE; addr < lowmem_end_addr; | 251 | for (addr = memstart + PPC_PIN_SIZE; addr < lowmem_end_addr; |
245 | addr += PPC_PIN_SIZE) { | 252 | addr += PPC_PIN_SIZE) { |
246 | if (mmu_has_feature(MMU_FTR_TYPE_47x)) | 253 | if (mmu_has_feature(MMU_FTR_TYPE_47x)) |
247 | ppc47x_pin_tlb(addr + PAGE_OFFSET, addr); | 254 | ppc47x_pin_tlb(addr + PAGE_OFFSET, addr); |
diff --git a/arch/powerpc/mm/tlb_hash32.c b/arch/powerpc/mm/tlb_hash32.c index 27b863c14941..9a445f64accd 100644 --- a/arch/powerpc/mm/tlb_hash32.c +++ b/arch/powerpc/mm/tlb_hash32.c | |||
@@ -177,3 +177,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
177 | flush_range(vma->vm_mm, start, end); | 177 | flush_range(vma->vm_mm, start, end); |
178 | } | 178 | } |
179 | EXPORT_SYMBOL(flush_tlb_range); | 179 | EXPORT_SYMBOL(flush_tlb_range); |
180 | |||
181 | void __init early_init_mmu(void) | ||
182 | { | ||
183 | } | ||
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index e80ed1093e2f..d32ec643c231 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/preempt.h> | 35 | #include <linux/preempt.h> |
36 | #include <linux/spinlock.h> | 36 | #include <linux/spinlock.h> |
37 | #include <linux/memblock.h> | 37 | #include <linux/memblock.h> |
38 | #include <linux/of_fdt.h> | ||
38 | 39 | ||
39 | #include <asm/tlbflush.h> | 40 | #include <asm/tlbflush.h> |
40 | #include <asm/tlb.h> | 41 | #include <asm/tlb.h> |
@@ -272,6 +273,17 @@ EXPORT_SYMBOL(flush_tlb_page); | |||
272 | 273 | ||
273 | #endif /* CONFIG_SMP */ | 274 | #endif /* CONFIG_SMP */ |
274 | 275 | ||
276 | #ifdef CONFIG_PPC_47x | ||
277 | void __init early_init_mmu_47x(void) | ||
278 | { | ||
279 | #ifdef CONFIG_SMP | ||
280 | unsigned long root = of_get_flat_dt_root(); | ||
281 | if (of_get_flat_dt_prop(root, "cooperative-partition", NULL)) | ||
282 | mmu_clear_feature(MMU_FTR_USE_TLBIVAX_BCAST); | ||
283 | #endif /* CONFIG_SMP */ | ||
284 | } | ||
285 | #endif /* CONFIG_PPC_47x */ | ||
286 | |||
275 | /* | 287 | /* |
276 | * Flush kernel TLB entries in the given range | 288 | * Flush kernel TLB entries in the given range |
277 | */ | 289 | */ |
@@ -599,4 +611,11 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base, | |||
599 | /* Finally limit subsequent allocations */ | 611 | /* Finally limit subsequent allocations */ |
600 | memblock_set_current_limit(first_memblock_base + ppc64_rma_size); | 612 | memblock_set_current_limit(first_memblock_base + ppc64_rma_size); |
601 | } | 613 | } |
614 | #else /* ! CONFIG_PPC64 */ | ||
615 | void __init early_init_mmu(void) | ||
616 | { | ||
617 | #ifdef CONFIG_PPC_47x | ||
618 | early_init_mmu_47x(); | ||
619 | #endif | ||
620 | } | ||
602 | #endif /* CONFIG_PPC64 */ | 621 | #endif /* CONFIG_PPC64 */ |
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 156aa7d36258..3cf59b661156 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c | |||
@@ -650,12 +650,74 @@ struct ppc4xx_pciex_hwops | |||
650 | int (*core_init)(struct device_node *np); | 650 | int (*core_init)(struct device_node *np); |
651 | int (*port_init_hw)(struct ppc4xx_pciex_port *port); | 651 | int (*port_init_hw)(struct ppc4xx_pciex_port *port); |
652 | int (*setup_utl)(struct ppc4xx_pciex_port *port); | 652 | int (*setup_utl)(struct ppc4xx_pciex_port *port); |
653 | void (*check_link)(struct ppc4xx_pciex_port *port); | ||
653 | }; | 654 | }; |
654 | 655 | ||
655 | static struct ppc4xx_pciex_hwops *ppc4xx_pciex_hwops; | 656 | static struct ppc4xx_pciex_hwops *ppc4xx_pciex_hwops; |
656 | 657 | ||
657 | #ifdef CONFIG_44x | 658 | #ifdef CONFIG_44x |
658 | 659 | ||
660 | static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port, | ||
661 | unsigned int sdr_offset, | ||
662 | unsigned int mask, | ||
663 | unsigned int value, | ||
664 | int timeout_ms) | ||
665 | { | ||
666 | u32 val; | ||
667 | |||
668 | while(timeout_ms--) { | ||
669 | val = mfdcri(SDR0, port->sdr_base + sdr_offset); | ||
670 | if ((val & mask) == value) { | ||
671 | pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n", | ||
672 | port->index, sdr_offset, timeout_ms, val); | ||
673 | return 0; | ||
674 | } | ||
675 | msleep(1); | ||
676 | } | ||
677 | return -1; | ||
678 | } | ||
679 | |||
680 | static int __init ppc4xx_pciex_port_reset_sdr(struct ppc4xx_pciex_port *port) | ||
681 | { | ||
682 | /* Wait for reset to complete */ | ||
683 | if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) { | ||
684 | printk(KERN_WARNING "PCIE%d: PGRST failed\n", | ||
685 | port->index); | ||
686 | return -1; | ||
687 | } | ||
688 | return 0; | ||
689 | } | ||
690 | |||
691 | static void __init ppc4xx_pciex_check_link_sdr(struct ppc4xx_pciex_port *port) | ||
692 | { | ||
693 | printk(KERN_INFO "PCIE%d: Checking link...\n", port->index); | ||
694 | |||
695 | /* Check for card presence detect if supported, if not, just wait for | ||
696 | * link unconditionally. | ||
697 | * | ||
698 | * note that we don't fail if there is no link, we just filter out | ||
699 | * config space accesses. That way, it will be easier to implement | ||
700 | * hotplug later on. | ||
701 | */ | ||
702 | if (!port->has_ibpre || | ||
703 | !ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP, | ||
704 | 1 << 28, 1 << 28, 100)) { | ||
705 | printk(KERN_INFO | ||
706 | "PCIE%d: Device detected, waiting for link...\n", | ||
707 | port->index); | ||
708 | if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP, | ||
709 | 0x1000, 0x1000, 2000)) | ||
710 | printk(KERN_WARNING | ||
711 | "PCIE%d: Link up failed\n", port->index); | ||
712 | else { | ||
713 | printk(KERN_INFO | ||
714 | "PCIE%d: link is up !\n", port->index); | ||
715 | port->link = 1; | ||
716 | } | ||
717 | } else | ||
718 | printk(KERN_INFO "PCIE%d: No device detected.\n", port->index); | ||
719 | } | ||
720 | |||
659 | /* Check various reset bits of the 440SPe PCIe core */ | 721 | /* Check various reset bits of the 440SPe PCIe core */ |
660 | static int __init ppc440spe_pciex_check_reset(struct device_node *np) | 722 | static int __init ppc440spe_pciex_check_reset(struct device_node *np) |
661 | { | 723 | { |
@@ -806,7 +868,7 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | |||
806 | dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, | 868 | dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, |
807 | (1 << 24) | (1 << 16), 1 << 12); | 869 | (1 << 24) | (1 << 16), 1 << 12); |
808 | 870 | ||
809 | return 0; | 871 | return ppc4xx_pciex_port_reset_sdr(port); |
810 | } | 872 | } |
811 | 873 | ||
812 | static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 874 | static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
@@ -856,6 +918,7 @@ static struct ppc4xx_pciex_hwops ppc440speA_pcie_hwops __initdata = | |||
856 | .core_init = ppc440spe_pciex_core_init, | 918 | .core_init = ppc440spe_pciex_core_init, |
857 | .port_init_hw = ppc440speA_pciex_init_port_hw, | 919 | .port_init_hw = ppc440speA_pciex_init_port_hw, |
858 | .setup_utl = ppc440speA_pciex_init_utl, | 920 | .setup_utl = ppc440speA_pciex_init_utl, |
921 | .check_link = ppc4xx_pciex_check_link_sdr, | ||
859 | }; | 922 | }; |
860 | 923 | ||
861 | static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata = | 924 | static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata = |
@@ -863,6 +926,7 @@ static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata = | |||
863 | .core_init = ppc440spe_pciex_core_init, | 926 | .core_init = ppc440spe_pciex_core_init, |
864 | .port_init_hw = ppc440speB_pciex_init_port_hw, | 927 | .port_init_hw = ppc440speB_pciex_init_port_hw, |
865 | .setup_utl = ppc440speB_pciex_init_utl, | 928 | .setup_utl = ppc440speB_pciex_init_utl, |
929 | .check_link = ppc4xx_pciex_check_link_sdr, | ||
866 | }; | 930 | }; |
867 | 931 | ||
868 | static int __init ppc460ex_pciex_core_init(struct device_node *np) | 932 | static int __init ppc460ex_pciex_core_init(struct device_node *np) |
@@ -944,7 +1008,7 @@ static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | |||
944 | 1008 | ||
945 | port->has_ibpre = 1; | 1009 | port->has_ibpre = 1; |
946 | 1010 | ||
947 | return 0; | 1011 | return ppc4xx_pciex_port_reset_sdr(port); |
948 | } | 1012 | } |
949 | 1013 | ||
950 | static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port) | 1014 | static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port) |
@@ -972,6 +1036,7 @@ static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata = | |||
972 | .core_init = ppc460ex_pciex_core_init, | 1036 | .core_init = ppc460ex_pciex_core_init, |
973 | .port_init_hw = ppc460ex_pciex_init_port_hw, | 1037 | .port_init_hw = ppc460ex_pciex_init_port_hw, |
974 | .setup_utl = ppc460ex_pciex_init_utl, | 1038 | .setup_utl = ppc460ex_pciex_init_utl, |
1039 | .check_link = ppc4xx_pciex_check_link_sdr, | ||
975 | }; | 1040 | }; |
976 | 1041 | ||
977 | static int __init ppc460sx_pciex_core_init(struct device_node *np) | 1042 | static int __init ppc460sx_pciex_core_init(struct device_node *np) |
@@ -1075,7 +1140,7 @@ static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | |||
1075 | 1140 | ||
1076 | port->has_ibpre = 1; | 1141 | port->has_ibpre = 1; |
1077 | 1142 | ||
1078 | return 0; | 1143 | return ppc4xx_pciex_port_reset_sdr(port); |
1079 | } | 1144 | } |
1080 | 1145 | ||
1081 | static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port) | 1146 | static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port) |
@@ -1089,6 +1154,7 @@ static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = { | |||
1089 | .core_init = ppc460sx_pciex_core_init, | 1154 | .core_init = ppc460sx_pciex_core_init, |
1090 | .port_init_hw = ppc460sx_pciex_init_port_hw, | 1155 | .port_init_hw = ppc460sx_pciex_init_port_hw, |
1091 | .setup_utl = ppc460sx_pciex_init_utl, | 1156 | .setup_utl = ppc460sx_pciex_init_utl, |
1157 | .check_link = ppc4xx_pciex_check_link_sdr, | ||
1092 | }; | 1158 | }; |
1093 | 1159 | ||
1094 | #endif /* CONFIG_44x */ | 1160 | #endif /* CONFIG_44x */ |
@@ -1154,7 +1220,7 @@ static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | |||
1154 | 1220 | ||
1155 | port->has_ibpre = 1; | 1221 | port->has_ibpre = 1; |
1156 | 1222 | ||
1157 | return 0; | 1223 | return ppc4xx_pciex_port_reset_sdr(port); |
1158 | } | 1224 | } |
1159 | 1225 | ||
1160 | static int ppc405ex_pciex_init_utl(struct ppc4xx_pciex_port *port) | 1226 | static int ppc405ex_pciex_init_utl(struct ppc4xx_pciex_port *port) |
@@ -1183,11 +1249,11 @@ static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata = | |||
1183 | .core_init = ppc405ex_pciex_core_init, | 1249 | .core_init = ppc405ex_pciex_core_init, |
1184 | .port_init_hw = ppc405ex_pciex_init_port_hw, | 1250 | .port_init_hw = ppc405ex_pciex_init_port_hw, |
1185 | .setup_utl = ppc405ex_pciex_init_utl, | 1251 | .setup_utl = ppc405ex_pciex_init_utl, |
1252 | .check_link = ppc4xx_pciex_check_link_sdr, | ||
1186 | }; | 1253 | }; |
1187 | 1254 | ||
1188 | #endif /* CONFIG_40x */ | 1255 | #endif /* CONFIG_40x */ |
1189 | 1256 | ||
1190 | |||
1191 | /* Check that the core has been initied and if not, do it */ | 1257 | /* Check that the core has been initied and if not, do it */ |
1192 | static int __init ppc4xx_pciex_check_core_init(struct device_node *np) | 1258 | static int __init ppc4xx_pciex_check_core_init(struct device_node *np) |
1193 | { | 1259 | { |
@@ -1261,26 +1327,6 @@ static void __init ppc4xx_pciex_port_init_mapping(struct ppc4xx_pciex_port *port | |||
1261 | dcr_write(port->dcrs, DCRO_PEGPL_MSGMSK, 0); | 1327 | dcr_write(port->dcrs, DCRO_PEGPL_MSGMSK, 0); |
1262 | } | 1328 | } |
1263 | 1329 | ||
1264 | static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port, | ||
1265 | unsigned int sdr_offset, | ||
1266 | unsigned int mask, | ||
1267 | unsigned int value, | ||
1268 | int timeout_ms) | ||
1269 | { | ||
1270 | u32 val; | ||
1271 | |||
1272 | while(timeout_ms--) { | ||
1273 | val = mfdcri(SDR0, port->sdr_base + sdr_offset); | ||
1274 | if ((val & mask) == value) { | ||
1275 | pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n", | ||
1276 | port->index, sdr_offset, timeout_ms, val); | ||
1277 | return 0; | ||
1278 | } | ||
1279 | msleep(1); | ||
1280 | } | ||
1281 | return -1; | ||
1282 | } | ||
1283 | |||
1284 | static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) | 1330 | static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) |
1285 | { | 1331 | { |
1286 | int rc = 0; | 1332 | int rc = 0; |
@@ -1291,40 +1337,8 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) | |||
1291 | if (rc != 0) | 1337 | if (rc != 0) |
1292 | return rc; | 1338 | return rc; |
1293 | 1339 | ||
1294 | printk(KERN_INFO "PCIE%d: Checking link...\n", | 1340 | if (ppc4xx_pciex_hwops->check_link) |
1295 | port->index); | 1341 | ppc4xx_pciex_hwops->check_link(port); |
1296 | |||
1297 | /* Wait for reset to complete */ | ||
1298 | if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) { | ||
1299 | printk(KERN_WARNING "PCIE%d: PGRST failed\n", | ||
1300 | port->index); | ||
1301 | return -1; | ||
1302 | } | ||
1303 | |||
1304 | /* Check for card presence detect if supported, if not, just wait for | ||
1305 | * link unconditionally. | ||
1306 | * | ||
1307 | * note that we don't fail if there is no link, we just filter out | ||
1308 | * config space accesses. That way, it will be easier to implement | ||
1309 | * hotplug later on. | ||
1310 | */ | ||
1311 | if (!port->has_ibpre || | ||
1312 | !ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP, | ||
1313 | 1 << 28, 1 << 28, 100)) { | ||
1314 | printk(KERN_INFO | ||
1315 | "PCIE%d: Device detected, waiting for link...\n", | ||
1316 | port->index); | ||
1317 | if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP, | ||
1318 | 0x1000, 0x1000, 2000)) | ||
1319 | printk(KERN_WARNING | ||
1320 | "PCIE%d: Link up failed\n", port->index); | ||
1321 | else { | ||
1322 | printk(KERN_INFO | ||
1323 | "PCIE%d: link is up !\n", port->index); | ||
1324 | port->link = 1; | ||
1325 | } | ||
1326 | } else | ||
1327 | printk(KERN_INFO "PCIE%d: No device detected.\n", port->index); | ||
1328 | 1342 | ||
1329 | /* | 1343 | /* |
1330 | * Initialize mapping: disable all regions and configure | 1344 | * Initialize mapping: disable all regions and configure |
@@ -1347,14 +1361,17 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) | |||
1347 | /* | 1361 | /* |
1348 | * Check for VC0 active and assert RDY. | 1362 | * Check for VC0 active and assert RDY. |
1349 | */ | 1363 | */ |
1350 | if (port->link && | 1364 | if (port->sdr_base) { |
1351 | ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, | 1365 | if (port->link && |
1352 | 1 << 16, 1 << 16, 5000)) { | 1366 | ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, |
1353 | printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index); | 1367 | 1 << 16, 1 << 16, 5000)) { |
1354 | port->link = 0; | 1368 | printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index); |
1369 | port->link = 0; | ||
1370 | } | ||
1371 | |||
1372 | dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20); | ||
1355 | } | 1373 | } |
1356 | 1374 | ||
1357 | dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20); | ||
1358 | msleep(100); | 1375 | msleep(100); |
1359 | 1376 | ||
1360 | return 0; | 1377 | return 0; |