diff options
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/cpm2_pic.c | 2 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_pci.c | 107 | ||||
-rw-r--r-- | arch/powerpc/sysdev/ipic.c | 2 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 2 | ||||
-rw-r--r-- | arch/powerpc/sysdev/ppc4xx_pci.c | 17 |
5 files changed, 94 insertions, 36 deletions
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index b16ca3ed65d..78f1f7cca0a 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c @@ -165,7 +165,7 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) edibit = (14 - (src - CPM2_IRQ_EXT1)); else if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0) - edibit = (31 - (src - CPM2_IRQ_PORTC15)); + edibit = (31 - (CPM2_IRQ_PORTC0 - src)); else return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL; diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index f611d0369cc..9817f63723d 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -28,63 +28,104 @@ #include <sysdev/fsl_pci.h> #if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) +static int __init setup_one_atmu(struct ccsr_pci __iomem *pci, + unsigned int index, const struct resource *res, + resource_size_t offset) +{ + resource_size_t pci_addr = res->start - offset; + resource_size_t phys_addr = res->start; + resource_size_t size = res->end - res->start + 1; + u32 flags = 0x80044000; /* enable & mem R/W */ + unsigned int i; + + pr_debug("PCI MEM resource start 0x%016llx, size 0x%016llx.\n", + (u64)res->start, (u64)size); + + if (res->flags & IORESOURCE_PREFETCH) + flags |= 0x10000000; /* enable relaxed ordering */ + + for (i = 0; size > 0; i++) { + unsigned int bits = min(__ilog2(size), + __ffs(pci_addr | phys_addr)); + + if (index + i >= 5) + return -1; + + out_be32(&pci->pow[index + i].potar, pci_addr >> 12); + out_be32(&pci->pow[index + i].potear, (u64)pci_addr >> 44); + out_be32(&pci->pow[index + i].powbar, phys_addr >> 12); + out_be32(&pci->pow[index + i].powar, flags | (bits - 1)); + + pci_addr += (resource_size_t)1U << bits; + phys_addr += (resource_size_t)1U << bits; + size -= (resource_size_t)1U << bits; + } + + return i; +} + /* atmu setup for fsl pci/pcie controller */ static void __init setup_pci_atmu(struct pci_controller *hose, struct resource *rsrc) { struct ccsr_pci __iomem *pci; - int i; + int i, j, n; pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n", (u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1); pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1); + if (!pci) { + dev_err(hose->parent, "Unable to map ATMU registers\n"); + return; + } - /* Disable all windows (except powar0 since its ignored) */ + /* Disable all windows (except powar0 since it's ignored) */ for(i = 1; i < 5; i++) out_be32(&pci->pow[i].powar, 0); for(i = 0; i < 3; i++) out_be32(&pci->piw[i].piwar, 0); /* Setup outbound MEM window */ - for(i = 0; i < 3; i++) - if (hose->mem_resources[i].flags & IORESOURCE_MEM){ - resource_size_t pci_addr_start = - hose->mem_resources[i].start - - hose->pci_mem_offset; - pr_debug("PCI MEM resource start 0x%016llx, size 0x%016llx.\n", - (u64)hose->mem_resources[i].start, - (u64)hose->mem_resources[i].end - - (u64)hose->mem_resources[i].start + 1); - out_be32(&pci->pow[i+1].potar, (pci_addr_start >> 12)); - out_be32(&pci->pow[i+1].potear, 0); - out_be32(&pci->pow[i+1].powbar, - (hose->mem_resources[i].start >> 12)); - /* Enable, Mem R/W */ - out_be32(&pci->pow[i+1].powar, 0x80044000 - | (__ilog2(hose->mem_resources[i].end - - hose->mem_resources[i].start + 1) - 1)); - } + for(i = 0, j = 1; i < 3; i++) { + if (!(hose->mem_resources[i].flags & IORESOURCE_MEM)) + continue; + + n = setup_one_atmu(pci, j, &hose->mem_resources[i], + hose->pci_mem_offset); + + if (n < 0 || j >= 5) { + pr_err("Ran out of outbound PCI ATMUs for resource %d!\n", i); + hose->mem_resources[i].flags |= IORESOURCE_DISABLED; + } else + j += n; + } /* Setup outbound IO window */ - if (hose->io_resource.flags & IORESOURCE_IO){ - pr_debug("PCI IO resource start 0x%016llx, size 0x%016llx, " - "phy base 0x%016llx.\n", - (u64)hose->io_resource.start, - (u64)hose->io_resource.end - (u64)hose->io_resource.start + 1, - (u64)hose->io_base_phys); - out_be32(&pci->pow[i+1].potar, (hose->io_resource.start >> 12)); - out_be32(&pci->pow[i+1].potear, 0); - out_be32(&pci->pow[i+1].powbar, (hose->io_base_phys >> 12)); - /* Enable, IO R/W */ - out_be32(&pci->pow[i+1].powar, 0x80088000 - | (__ilog2(hose->io_resource.end - - hose->io_resource.start + 1) - 1)); + if (hose->io_resource.flags & IORESOURCE_IO) { + if (j >= 5) { + pr_err("Ran out of outbound PCI ATMUs for IO resource\n"); + } else { + pr_debug("PCI IO resource start 0x%016llx, size 0x%016llx, " + "phy base 0x%016llx.\n", + (u64)hose->io_resource.start, + (u64)hose->io_resource.end - (u64)hose->io_resource.start + 1, + (u64)hose->io_base_phys); + out_be32(&pci->pow[j].potar, (hose->io_resource.start >> 12)); + out_be32(&pci->pow[j].potear, 0); + out_be32(&pci->pow[j].powbar, (hose->io_base_phys >> 12)); + /* Enable, IO R/W */ + out_be32(&pci->pow[j].powar, 0x80088000 + | (__ilog2(hose->io_resource.end + - hose->io_resource.start + 1) - 1)); + } } /* Setup 2G inbound Memory Window @ 1 */ out_be32(&pci->piw[2].pitar, 0x00000000); out_be32(&pci->piw[2].piwbar,0x00000000); out_be32(&pci->piw[2].piwar, PIWAR_2G); + + iounmap(pci); } static void __init setup_pci_cmd(struct pci_controller *hose) diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index 88a983ece5c..9a89cd3e80a 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c @@ -890,7 +890,7 @@ unsigned int ipic_get_irq(void) return irq_linear_revmap(primary_ipic->irqhost, irq); } -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND static struct { u32 sicfr; u32 siprr[2]; diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 3e0d89dcdba..a35297dbac2 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -435,7 +435,7 @@ static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase, addr = addr | ((u64)readl(base + HT_MSI_ADDR_HI) << 32); } - printk(KERN_DEBUG "mpic: - HT:%02x.%x %s MSI mapping found @ 0x%lx\n", + printk(KERN_DEBUG "mpic: - HT:%02x.%x %s MSI mapping found @ 0x%llx\n", PCI_SLOT(devfn), PCI_FUNC(devfn), flags & HT_MSI_FLAGS_ENABLE ? "enabled" : "disabled", addr); diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 77fae5f64f2..5558d932b4d 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -204,6 +204,23 @@ static int __init ppc4xx_setup_one_pci_PMM(struct pci_controller *hose, { u32 ma, pcila, pciha; + /* Hack warning ! The "old" PCI 2.x cell only let us configure the low + * 32-bit of incoming PLB addresses. The top 4 bits of the 36-bit + * address are actually hard wired to a value that appears to depend + * on the specific SoC. For example, it's 0 on 440EP and 1 on 440EPx. + * + * The trick here is we just crop those top bits and ignore them when + * programming the chip. That means the device-tree has to be right + * for the specific part used (we don't print a warning if it's wrong + * but on the other hand, you'll crash quickly enough), but at least + * this code should work whatever the hard coded value is + */ + plb_addr &= 0xffffffffull; + + /* Note: Due to the above hack, the test below doesn't actually test + * if you address is above 4G, but it tests that address and + * (address + size) are both contained in the same 4G + */ if ((plb_addr + size) > 0xffffffffull || !is_power_of_2(size) || size < 0x1000 || (plb_addr & (size - 1)) != 0) { printk(KERN_WARNING "%s: Resource out of range\n", |