aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-07-21 23:16:41 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-07-21 23:16:41 -0400
commit4b575f3e8aba07688fc48025efde41036e5d5eee (patch)
tree4bbccce83e80af179500be45f9e8080315f5e32e
parentf7723f0eaf53d51ee54374116b25ac33e0be8542 (diff)
parenta8e616b9a41212655042f59c969f30bb7de1ec73 (diff)
Merge remote-tracking branch 'jwb/next' into next
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/powerpc/Kconfig2
-rw-r--r--arch/powerpc/boot/dts/taishan.dts4
-rw-r--r--arch/powerpc/boot/treeboot-iss4xx.c23
-rw-r--r--arch/powerpc/configs/44x/iss476-smp_defconfig6
-rw-r--r--arch/powerpc/include/asm/mmu.h7
-rw-r--r--arch/powerpc/kernel/head_44x.S42
-rw-r--r--arch/powerpc/kernel/setup_32.c2
-rw-r--r--arch/powerpc/mm/44x_mmu.c13
-rw-r--r--arch/powerpc/mm/tlb_hash32.c4
-rw-r--r--arch/powerpc/mm/tlb_nohash.c19
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.c147
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/
3876F: arch/powerpc/platforms/52xx/ 3876F: arch/powerpc/platforms/52xx/
3877 3877
3878LINUX FOR POWERPC EMBEDDED PPC4XX 3878LINUX FOR POWERPC EMBEDDED PPC4XX
3879M: Josh Boyer <jwboyer@linux.vnet.ibm.com> 3879M: Josh Boyer <jwboyer@gmail.com>
3880M: Matt Porter <mporter@kernel.crashing.org> 3880M: Matt Porter <mporter@kernel.crashing.org>
3881W: http://www.penguinppc.org/ 3881W: http://www.penguinppc.org/
3882L: linuxppc-dev@lists.ozlabs.org 3882L: 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
843config RELOCATABLE 843config 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
35BSS_STACK(4096); 35BSS_STACK(4096);
36 36
37static u32 ibm4xx_memstart;
38
37static void iss_4xx_fixups(void) 39static 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
57static 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
3CONFIG_EXPERIMENTAL=y 3CONFIG_EXPERIMENTAL=y
4CONFIG_SYSVIPC=y 4CONFIG_SYSVIPC=y
5CONFIG_POSIX_MQUEUE=y 5CONFIG_POSIX_MQUEUE=y
6CONFIG_SPARSE_IRQ=y
6CONFIG_LOG_BUF_SHIFT=14 7CONFIG_LOG_BUF_SHIFT=14
7CONFIG_SYSFS_DEPRECATED_V2=y
8CONFIG_BLK_DEV_INITRD=y 8CONFIG_BLK_DEV_INITRD=y
9# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set 9# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
10CONFIG_EXPERT=y 10CONFIG_EXPERT=y
@@ -21,10 +21,11 @@ CONFIG_ISS4xx=y
21CONFIG_HZ_100=y 21CONFIG_HZ_100=y
22CONFIG_MATH_EMULATION=y 22CONFIG_MATH_EMULATION=y
23CONFIG_IRQ_ALL_CPUS=y 23CONFIG_IRQ_ALL_CPUS=y
24CONFIG_SPARSE_IRQ=y
25CONFIG_CMDLINE_BOOL=y 24CONFIG_CMDLINE_BOOL=y
26CONFIG_CMDLINE="root=/dev/issblk0" 25CONFIG_CMDLINE="root=/dev/issblk0"
27# CONFIG_PCI is not set 26# CONFIG_PCI is not set
27CONFIG_ADVANCED_OPTIONS=y
28CONFIG_RELOCATABLE=y
28CONFIG_NET=y 29CONFIG_NET=y
29CONFIG_PACKET=y 30CONFIG_PACKET=y
30CONFIG_UNIX=y 31CONFIG_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
68CONFIG_EXT3_FS_POSIX_ACL=y 69CONFIG_EXT3_FS_POSIX_ACL=y
69CONFIG_EXT3_FS_SECURITY=y 70CONFIG_EXT3_FS_SECURITY=y
70CONFIG_INOTIFY=y
71CONFIG_PROC_KCORE=y 71CONFIG_PROC_KCORE=y
72CONFIG_TMPFS=y 72CONFIG_TMPFS=y
73CONFIG_CRAMFS=y 73CONFIG_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
128static inline void mmu_clear_feature(unsigned long feature)
129{
130 cur_cpu_spec->mmu_features &= ~feature;
131}
132
128extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup; 133extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup;
129 134
130/* MMU initialization (64-bit only fo now) */ 135/* MMU initialization */
131extern void early_init_mmu(void); 136extern void early_init_mmu(void);
132extern void early_init_mmu_secondary(void); 137extern 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)
186unsigned long __init mmu_mapin_ram(unsigned long top) 186unsigned 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)
218void setup_initial_memory_limit(phys_addr_t first_memblock_base, 219void 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
231void __cpuinit mmu_init_secondary(int cpu) 237void __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}
179EXPORT_SYMBOL(flush_tlb_range); 179EXPORT_SYMBOL(flush_tlb_range);
180
181void __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
277void __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 */
615void __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
655static struct ppc4xx_pciex_hwops *ppc4xx_pciex_hwops; 656static struct ppc4xx_pciex_hwops *ppc4xx_pciex_hwops;
656 657
657#ifdef CONFIG_44x 658#ifdef CONFIG_44x
658 659
660static 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
680static 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
691static 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 */
660static int __init ppc440spe_pciex_check_reset(struct device_node *np) 722static 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
812static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port) 874static 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
861static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata = 924static 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
868static int __init ppc460ex_pciex_core_init(struct device_node *np) 932static 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
950static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port) 1014static 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
977static int __init ppc460sx_pciex_core_init(struct device_node *np) 1042static 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
1081static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port) 1146static 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
1160static int ppc405ex_pciex_init_utl(struct ppc4xx_pciex_port *port) 1226static 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 */
1192static int __init ppc4xx_pciex_check_core_init(struct device_node *np) 1258static 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
1264static 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
1284static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) 1330static 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;