diff options
-rw-r--r-- | arch/powerpc/sysdev/fsl_pci.c | 104 |
1 files changed, 71 insertions, 33 deletions
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index f611d0369cc8..44bc903ead74 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
@@ -28,63 +28,101 @@ | |||
28 | #include <sysdev/fsl_pci.h> | 28 | #include <sysdev/fsl_pci.h> |
29 | 29 | ||
30 | #if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) | 30 | #if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) |
31 | static int __init setup_one_atmu(struct ccsr_pci __iomem *pci, | ||
32 | unsigned int index, const struct resource *res, | ||
33 | resource_size_t offset) | ||
34 | { | ||
35 | resource_size_t pci_addr = res->start - offset; | ||
36 | resource_size_t phys_addr = res->start; | ||
37 | resource_size_t size = res->end - res->start + 1; | ||
38 | u32 flags = 0x80044000; /* enable & mem R/W */ | ||
39 | unsigned int i; | ||
40 | |||
41 | pr_debug("PCI MEM resource start 0x%016llx, size 0x%016llx.\n", | ||
42 | (u64)res->start, (u64)size); | ||
43 | |||
44 | for (i = 0; size > 0; i++) { | ||
45 | unsigned int bits = min(__ilog2(size), | ||
46 | __ffs(pci_addr | phys_addr)); | ||
47 | |||
48 | if (index + i >= 5) | ||
49 | return -1; | ||
50 | |||
51 | out_be32(&pci->pow[index + i].potar, pci_addr >> 12); | ||
52 | out_be32(&pci->pow[index + i].potear, (u64)pci_addr >> 44); | ||
53 | out_be32(&pci->pow[index + i].powbar, phys_addr >> 12); | ||
54 | out_be32(&pci->pow[index + i].powar, flags | (bits - 1)); | ||
55 | |||
56 | pci_addr += (resource_size_t)1U << bits; | ||
57 | phys_addr += (resource_size_t)1U << bits; | ||
58 | size -= (resource_size_t)1U << bits; | ||
59 | } | ||
60 | |||
61 | return i; | ||
62 | } | ||
63 | |||
31 | /* atmu setup for fsl pci/pcie controller */ | 64 | /* atmu setup for fsl pci/pcie controller */ |
32 | static void __init setup_pci_atmu(struct pci_controller *hose, | 65 | static void __init setup_pci_atmu(struct pci_controller *hose, |
33 | struct resource *rsrc) | 66 | struct resource *rsrc) |
34 | { | 67 | { |
35 | struct ccsr_pci __iomem *pci; | 68 | struct ccsr_pci __iomem *pci; |
36 | int i; | 69 | int i, j, n; |
37 | 70 | ||
38 | pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n", | 71 | pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n", |
39 | (u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1); | 72 | (u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1); |
40 | pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1); | 73 | pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1); |
74 | if (!pci) { | ||
75 | dev_err(hose->parent, "Unable to map ATMU registers\n"); | ||
76 | return; | ||
77 | } | ||
41 | 78 | ||
42 | /* Disable all windows (except powar0 since its ignored) */ | 79 | /* Disable all windows (except powar0 since it's ignored) */ |
43 | for(i = 1; i < 5; i++) | 80 | for(i = 1; i < 5; i++) |
44 | out_be32(&pci->pow[i].powar, 0); | 81 | out_be32(&pci->pow[i].powar, 0); |
45 | for(i = 0; i < 3; i++) | 82 | for(i = 0; i < 3; i++) |
46 | out_be32(&pci->piw[i].piwar, 0); | 83 | out_be32(&pci->piw[i].piwar, 0); |
47 | 84 | ||
48 | /* Setup outbound MEM window */ | 85 | /* Setup outbound MEM window */ |
49 | for(i = 0; i < 3; i++) | 86 | for(i = 0, j = 1; i < 3; i++) { |
50 | if (hose->mem_resources[i].flags & IORESOURCE_MEM){ | 87 | if (!(hose->mem_resources[i].flags & IORESOURCE_MEM)) |
51 | resource_size_t pci_addr_start = | 88 | continue; |
52 | hose->mem_resources[i].start - | 89 | |
53 | hose->pci_mem_offset; | 90 | n = setup_one_atmu(pci, j, &hose->mem_resources[i], |
54 | pr_debug("PCI MEM resource start 0x%016llx, size 0x%016llx.\n", | 91 | hose->pci_mem_offset); |
55 | (u64)hose->mem_resources[i].start, | 92 | |
56 | (u64)hose->mem_resources[i].end | 93 | if (n < 0 || j >= 5) { |
57 | - (u64)hose->mem_resources[i].start + 1); | 94 | pr_err("Ran out of outbound PCI ATMUs for resource %d!\n", i); |
58 | out_be32(&pci->pow[i+1].potar, (pci_addr_start >> 12)); | 95 | hose->mem_resources[i].flags |= IORESOURCE_DISABLED; |
59 | out_be32(&pci->pow[i+1].potear, 0); | 96 | } else |
60 | out_be32(&pci->pow[i+1].powbar, | 97 | j += n; |
61 | (hose->mem_resources[i].start >> 12)); | 98 | } |
62 | /* Enable, Mem R/W */ | ||
63 | out_be32(&pci->pow[i+1].powar, 0x80044000 | ||
64 | | (__ilog2(hose->mem_resources[i].end | ||
65 | - hose->mem_resources[i].start + 1) - 1)); | ||
66 | } | ||
67 | 99 | ||
68 | /* Setup outbound IO window */ | 100 | /* Setup outbound IO window */ |
69 | if (hose->io_resource.flags & IORESOURCE_IO){ | 101 | if (hose->io_resource.flags & IORESOURCE_IO) { |
70 | pr_debug("PCI IO resource start 0x%016llx, size 0x%016llx, " | 102 | if (j >= 5) { |
71 | "phy base 0x%016llx.\n", | 103 | pr_err("Ran out of outbound PCI ATMUs for IO resource\n"); |
72 | (u64)hose->io_resource.start, | 104 | } else { |
73 | (u64)hose->io_resource.end - (u64)hose->io_resource.start + 1, | 105 | pr_debug("PCI IO resource start 0x%016llx, size 0x%016llx, " |
74 | (u64)hose->io_base_phys); | 106 | "phy base 0x%016llx.\n", |
75 | out_be32(&pci->pow[i+1].potar, (hose->io_resource.start >> 12)); | 107 | (u64)hose->io_resource.start, |
76 | out_be32(&pci->pow[i+1].potear, 0); | 108 | (u64)hose->io_resource.end - (u64)hose->io_resource.start + 1, |
77 | out_be32(&pci->pow[i+1].powbar, (hose->io_base_phys >> 12)); | 109 | (u64)hose->io_base_phys); |
78 | /* Enable, IO R/W */ | 110 | out_be32(&pci->pow[j].potar, (hose->io_resource.start >> 12)); |
79 | out_be32(&pci->pow[i+1].powar, 0x80088000 | 111 | out_be32(&pci->pow[j].potear, 0); |
80 | | (__ilog2(hose->io_resource.end | 112 | out_be32(&pci->pow[j].powbar, (hose->io_base_phys >> 12)); |
81 | - hose->io_resource.start + 1) - 1)); | 113 | /* Enable, IO R/W */ |
114 | out_be32(&pci->pow[j].powar, 0x80088000 | ||
115 | | (__ilog2(hose->io_resource.end | ||
116 | - hose->io_resource.start + 1) - 1)); | ||
117 | } | ||
82 | } | 118 | } |
83 | 119 | ||
84 | /* Setup 2G inbound Memory Window @ 1 */ | 120 | /* Setup 2G inbound Memory Window @ 1 */ |
85 | out_be32(&pci->piw[2].pitar, 0x00000000); | 121 | out_be32(&pci->piw[2].pitar, 0x00000000); |
86 | out_be32(&pci->piw[2].piwbar,0x00000000); | 122 | out_be32(&pci->piw[2].piwbar,0x00000000); |
87 | out_be32(&pci->piw[2].piwar, PIWAR_2G); | 123 | out_be32(&pci->piw[2].piwar, PIWAR_2G); |
124 | |||
125 | iounmap(pci); | ||
88 | } | 126 | } |
89 | 127 | ||
90 | static void __init setup_pci_cmd(struct pci_controller *hose) | 128 | static void __init setup_pci_cmd(struct pci_controller *hose) |