Currently pci_32 doesn't support 64-bit physical addresses, while
PowerPC440 platform has PCI space typically mapped above 4GB range.
The patch adds 64-bit physical address support to 32-bit PCI code
in order to bring-up PCI on 44x platform.

Signed-off-by: Valentine Barshak <[EMAIL PROTECTED]>
---
 arch/powerpc/kernel/iomap.c  |    4 +--
 arch/powerpc/kernel/pci_32.c |   56 +++++++++++++++++++++++++++++--------------
 2 files changed, 41 insertions(+), 19 deletions(-)

diff -ruN linux-2.6.orig/arch/powerpc/kernel/iomap.c 
linux-2.6/arch/powerpc/kernel/iomap.c
--- linux-2.6.orig/arch/powerpc/kernel/iomap.c  2007-09-18 15:32:19.000000000 
+0400
+++ linux-2.6/arch/powerpc/kernel/iomap.c       2007-09-18 17:26:35.000000000 
+0400
@@ -119,8 +119,8 @@
 
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
 {
-       unsigned long start = pci_resource_start(dev, bar);
-       unsigned long len = pci_resource_len(dev, bar);
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
        unsigned long flags = pci_resource_flags(dev, bar);
 
        if (!len)
diff -ruN linux-2.6.orig/arch/powerpc/kernel/pci_32.c 
linux-2.6/arch/powerpc/kernel/pci_32.c
--- linux-2.6.orig/arch/powerpc/kernel/pci_32.c 2007-09-18 15:32:19.000000000 
+0400
+++ linux-2.6/arch/powerpc/kernel/pci_32.c      2007-09-18 18:17:00.000000000 
+0400
@@ -105,7 +105,7 @@
 {
        struct pci_controller* hose = (struct pci_controller *)dev->sysdata;
        int i;
-       unsigned long offset;
+       resource_size_t offset;
 
        if (!hose) {
                printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev));
@@ -115,7 +115,7 @@
                struct resource *res = dev->resource + i;
                if (!res->flags)
                        continue;
-               if (res->end == 0xffffffff) {
+               if (res->end == (resource_size_t) -1) {
                        DBG("PCI:%s Resource %d [%016llx-%016llx] is 
unassigned\n",
                            pci_name(dev), i, (u64)res->start, (u64)res->end);
                        res->end -= res->start;
@@ -148,7 +148,7 @@
 void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region 
*region,
                        struct resource *res)
 {
-       unsigned long offset = 0;
+       resource_size_t offset = 0;
        struct pci_controller *hose = dev->sysdata;
 
        if (hose && res->flags & IORESOURCE_IO)
@@ -163,7 +163,7 @@
 void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
                             struct pci_bus_region *region)
 {
-       unsigned long offset = 0;
+       resource_size_t offset = 0;
        struct pci_controller *hose = dev->sysdata;
 
        if (hose && res->flags & IORESOURCE_IO)
@@ -439,7 +439,7 @@
        u8 io_base_lo, io_limit_lo;
        u16 mem_base, mem_limit;
        u16 cmd;
-       unsigned long start, end, off;
+       resource_size_t start, end, off;
        struct pci_controller *hose = dev->sysdata;
 
        if (!hose) {
@@ -843,16 +843,28 @@
 }
 EXPORT_SYMBOL(pci_device_from_OF_node);
 
+
+static inline u64 pci_get_range64(u32 *r)
+{
+       return (((u64)r[0] << 32) | r[1]);
+}
+
+
 void __init
 pci_process_bridge_OF_ranges(struct pci_controller *hose,
                           struct device_node *dev, int primary)
 {
        static unsigned int static_lc_ranges[256] __initdata;
        const unsigned int *dt_ranges;
-       unsigned int *lc_ranges, *ranges, *prev, size;
+       unsigned int *lc_ranges, *ranges, *prev;
        int rlen = 0, orig_rlen;
        int memno = 0;
        struct resource *res;
+       u32 prev_pci_space, pci_space;
+       u64 prev_pci_addr, pci_addr;
+       u64 prev_size, size;
+       phys_addr_t cpu_phys_addr;
+       
        int np, na = of_n_addr_cells(dev);
        np = na + 5;
 
@@ -879,11 +891,18 @@
        prev = NULL;
        while ((rlen -= np * sizeof(unsigned int)) >= 0) {
                if (prev) {
-                       if (prev[0] == ranges[0] && prev[1] == ranges[1] &&
-                               (prev[2] + prev[na+4]) == ranges[2] &&
-                               (prev[na+2] + prev[na+4]) == ranges[na+2]) {
-                               prev[na+4] += ranges[na+4];
+                       prev_pci_space = prev[0];
+                       prev_pci_addr = pci_get_range64(&prev[1]);
+                       prev_size = pci_get_range64(&prev[na+3]);
+                       pci_space = ranges[0];
+                       pci_addr = pci_get_range64(&ranges[1]);
+                       if ((prev_pci_space == pci_space) && 
+                           ((prev_pci_addr + prev_size) == pci_addr)) {
+                               size = pci_get_range64(&ranges[na+3]);
+                               prev_size += size;
                                ranges[0] = 0;
+                               prev[na+3] = (u32)((prev_size >> 32) & 
0xffffffff);
+                               prev[na+4] = (u32)(prev_size & 0xffffffff);
                                ranges += np;
                                continue;
                        }
@@ -904,21 +923,22 @@
        rlen = orig_rlen;
        while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {
                res = NULL;
-               size = ranges[na+4];
-               switch ((ranges[0] >> 24) & 0x3) {
+               size = pci_get_range64(&ranges[na+3]);
+               pci_space = ranges[0] >> 24;
+               switch (pci_space & 0x3) {
                case 1:         /* I/O space */
                        if (ranges[2] != 0)
                                break;
-                       hose->io_base_phys = ranges[na+2];
+                       hose->io_base_phys = of_translate_address(dev, 
&ranges[3]);
                        /* limit I/O space to 16MB */
                        if (size > 0x01000000)
                                size = 0x01000000;
-                       hose->io_base_virt = ioremap(ranges[na+2], size);
+                       hose->io_base_virt = ioremap(hose->io_base_phys, size);
                        if (primary)
                                isa_io_base = (unsigned long) 
hose->io_base_virt;
                        res = &hose->io_resource;
                        res->flags = IORESOURCE_IO;
-                       res->start = ranges[2];
+                       res->start = pci_get_range64(&ranges[1]);
                        DBG("PCI: IO 0x%llx -> 0x%llx\n",
                            (u64)res->start, (u64)res->start + size - 1);
                        break;
@@ -933,14 +953,16 @@
                        }
                        while (memno < 3 && hose->mem_resources[memno].flags)
                                ++memno;
+                       pci_addr = pci_get_range64(&ranges[1]);
+                       cpu_phys_addr = of_translate_address(dev, &ranges[3]);
                        if (memno == 0)
-                               hose->pci_mem_offset = ranges[na+2] - ranges[2];
+                               hose->pci_mem_offset = (u64)cpu_phys_addr - 
pci_addr;
                        if (memno < 3) {
                                res = &hose->mem_resources[memno];
                                res->flags = IORESOURCE_MEM;
                                if(ranges[0] & 0x40000000)
                                        res->flags |= IORESOURCE_PREFETCH;
-                               res->start = ranges[na+2];
+                               res->start = cpu_phys_addr;
                                DBG("PCI: MEM[%d] 0x%llx -> 0x%llx\n", memno,
                                    (u64)res->start, (u64)res->start + size - 
1);
                        }
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Reply via email to