aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/pci_64.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2007-12-10 22:48:18 -0500
committerPaul Mackerras <paulus@samba.org>2007-12-10 23:43:35 -0500
commit13dccb9e65dc0fa4de83e5bd5639f7a7f3f6fb9e (patch)
treee072ef034d6021359993253d1101ba7a03609760 /arch/powerpc/kernel/pci_64.c
parent25e81f925d4be0a0f60520e1c3c1b5af744404e1 (diff)
[POWERPC] Merge pci_process_bridge_OF_ranges()
This merges the 32-bit and 64-bit implementations of pci_process_bridge_OF_ranges(). The new function is cleaner than both the old ones, and supports 64 bits ranges on ppc32 which is necessary for the 4xx port. It also adds some better (hopefully) output to the kernel log which should help diagnose problems and makes better use of existing OF parsing helpers (avoiding a few bugs of both implementations along the way). There are still a few unfortunate ifdef's but there is no way around these for now at least not until some other bits of the PCI code are made common. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/pci_64.c')
-rw-r--r--arch/powerpc/kernel/pci_64.c93
1 files changed, 0 insertions, 93 deletions
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 6b9a8564e735..bf06926f677d 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -578,99 +578,6 @@ int pci_proc_domain(struct pci_bus *bus)
578 return hose->buid != 0; 578 return hose->buid != 0;
579} 579}
580 580
581void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
582 struct device_node *dev, int prim)
583{
584 const unsigned int *ranges;
585 unsigned int pci_space;
586 unsigned long size;
587 int rlen = 0;
588 int memno = 0;
589 struct resource *res;
590 int np, na = of_n_addr_cells(dev);
591 unsigned long pci_addr, cpu_phys_addr;
592
593 np = na + 5;
594
595 /* From "PCI Binding to 1275"
596 * The ranges property is laid out as an array of elements,
597 * each of which comprises:
598 * cells 0 - 2: a PCI address
599 * cells 3 or 3+4: a CPU physical address
600 * (size depending on dev->n_addr_cells)
601 * cells 4+5 or 5+6: the size of the range
602 */
603 ranges = of_get_property(dev, "ranges", &rlen);
604 if (ranges == NULL)
605 return;
606 hose->io_base_phys = 0;
607 while ((rlen -= np * sizeof(unsigned int)) >= 0) {
608 res = NULL;
609 pci_space = ranges[0];
610 pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2];
611 cpu_phys_addr = of_translate_address(dev, &ranges[3]);
612 size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4];
613 ranges += np;
614 if (size == 0)
615 continue;
616
617 /* Now consume following elements while they are contiguous */
618 while (rlen >= np * sizeof(unsigned int)) {
619 unsigned long addr, phys;
620
621 if (ranges[0] != pci_space)
622 break;
623 addr = ((unsigned long)ranges[1] << 32) | ranges[2];
624 phys = ranges[3];
625 if (na >= 2)
626 phys = (phys << 32) | ranges[4];
627 if (addr != pci_addr + size ||
628 phys != cpu_phys_addr + size)
629 break;
630
631 size += ((unsigned long)ranges[na+3] << 32)
632 | ranges[na+4];
633 ranges += np;
634 rlen -= np * sizeof(unsigned int);
635 }
636
637 switch ((pci_space >> 24) & 0x3) {
638 case 1: /* I/O space */
639 hose->io_base_phys = cpu_phys_addr - pci_addr;
640 /* handle from 0 to top of I/O window */
641 hose->pci_io_size = pci_addr + size;
642
643 res = &hose->io_resource;
644 res->flags = IORESOURCE_IO;
645 res->start = pci_addr;
646 DBG("phb%d: IO 0x%lx -> 0x%lx\n", hose->global_number,
647 res->start, res->start + size - 1);
648 break;
649 case 2: /* memory space */
650 memno = 0;
651 while (memno < 3 && hose->mem_resources[memno].flags)
652 ++memno;
653
654 if (memno == 0)
655 hose->pci_mem_offset = cpu_phys_addr - pci_addr;
656 if (memno < 3) {
657 res = &hose->mem_resources[memno];
658 res->flags = IORESOURCE_MEM;
659 res->start = cpu_phys_addr;
660 DBG("phb%d: MEM 0x%lx -> 0x%lx\n", hose->global_number,
661 res->start, res->start + size - 1);
662 }
663 break;
664 }
665 if (res != NULL) {
666 res->name = dev->full_name;
667 res->end = res->start + size - 1;
668 res->parent = NULL;
669 res->sibling = NULL;
670 res->child = NULL;
671 }
672 }
673}
674 581
675#ifdef CONFIG_HOTPLUG 582#ifdef CONFIG_HOTPLUG
676 583