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