diff options
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) |
