pci-common.c (d92a208d086063ecc785b4588f74ab42268cbc4b) pci-common.c (654837e8fe8d1d302803458e3a100aa78e0d90de)
1/*
2 * Contains common pci routines for ALL ppc platform
3 * (based on pci_32.c and pci_64.c)
4 *
5 * Port for PPC64 David Engebretsen, IBM Corp.
6 * Contains common pci routines for ppc64 platform, pSeries and iSeries brands.
7 *
8 * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM

--- 672 unchanged lines hidden (view full) ---

681 * it for 64 bits but I would expect problems on 32 bits.
682 *
683 * - Some 32 bits platforms such as 4xx can have physical space larger than
684 * 32 bits so we need to use 64 bits values for the parsing
685 */
686void pci_process_bridge_OF_ranges(struct pci_controller *hose,
687 struct device_node *dev, int primary)
688{
1/*
2 * Contains common pci routines for ALL ppc platform
3 * (based on pci_32.c and pci_64.c)
4 *
5 * Port for PPC64 David Engebretsen, IBM Corp.
6 * Contains common pci routines for ppc64 platform, pSeries and iSeries brands.
7 *
8 * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM

--- 672 unchanged lines hidden (view full) ---

681 * it for 64 bits but I would expect problems on 32 bits.
682 *
683 * - Some 32 bits platforms such as 4xx can have physical space larger than
684 * 32 bits so we need to use 64 bits values for the parsing
685 */
686void pci_process_bridge_OF_ranges(struct pci_controller *hose,
687 struct device_node *dev, int primary)
688{
689 const __be32 *ranges;
690 int rlen;
691 int pna = of_n_addr_cells(dev);
692 int np = pna + 5;
693 int memno = 0;
689 int memno = 0;
694 u32 pci_space;
695 unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;
696 struct resource *res;
690 struct resource *res;
691 struct of_pci_range range;
692 struct of_pci_range_parser parser;
697
698 printk(KERN_INFO "PCI host bridge %s %s ranges:\n",
699 dev->full_name, primary ? "(primary)" : "");
700
693
694 printk(KERN_INFO "PCI host bridge %s %s ranges:\n",
695 dev->full_name, primary ? "(primary)" : "");
696
701 /* Get ranges property */
702 ranges = of_get_property(dev, "ranges", &rlen);
703 if (ranges == NULL)
697 /* Check for ranges property */
698 if (of_pci_range_parser_init(&parser, dev))
704 return;
705
706 /* Parse it */
699 return;
700
701 /* Parse it */
707 while ((rlen -= np * 4) >= 0) {
708 /* Read next ranges element */
709 pci_space = of_read_number(ranges, 1);
710 pci_addr = of_read_number(ranges + 1, 2);
711 cpu_addr = of_translate_address(dev, ranges + 3);
712 size = of_read_number(ranges + pna + 3, 2);
713 ranges += np;
714
702 for_each_of_pci_range(&parser, &range) {
715 /* If we failed translation or got a zero-sized region
716 * (some FW try to feed us with non sensical zero sized regions
717 * such as power3 which look like some kind of attempt at exposing
718 * the VGA memory hole)
719 */
703 /* If we failed translation or got a zero-sized region
704 * (some FW try to feed us with non sensical zero sized regions
705 * such as power3 which look like some kind of attempt at exposing
706 * the VGA memory hole)
707 */
720 if (cpu_addr == OF_BAD_ADDR || size == 0)
708 if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
721 continue;
722
709 continue;
710
723 /* Now consume following elements while they are contiguous */
724 for (; rlen >= np * sizeof(u32);
725 ranges += np, rlen -= np * 4) {
726 if (of_read_number(ranges, 1) != pci_space)
727 break;
728 pci_next = of_read_number(ranges + 1, 2);
729 cpu_next = of_translate_address(dev, ranges + 3);
730 if (pci_next != pci_addr + size ||
731 cpu_next != cpu_addr + size)
732 break;
733 size += of_read_number(ranges + pna + 3, 2);
734 }
735
736 /* Act based on address space type */
737 res = NULL;
711 /* Act based on address space type */
712 res = NULL;
738 switch ((pci_space >> 24) & 0x3) {
739 case 1: /* PCI IO space */
713 switch (range.flags & IORESOURCE_TYPE_BITS) {
714 case IORESOURCE_IO:
740 printk(KERN_INFO
741 " IO 0x%016llx..0x%016llx -> 0x%016llx\n",
715 printk(KERN_INFO
716 " IO 0x%016llx..0x%016llx -> 0x%016llx\n",
742 cpu_addr, cpu_addr + size - 1, pci_addr);
717 range.cpu_addr, range.cpu_addr + range.size - 1,
718 range.pci_addr);
743
744 /* We support only one IO range */
745 if (hose->pci_io_size) {
746 printk(KERN_INFO
747 " \\--> Skipped (too many) !\n");
748 continue;
749 }
750#ifdef CONFIG_PPC32
751 /* On 32 bits, limit I/O space to 16MB */
719
720 /* We support only one IO range */
721 if (hose->pci_io_size) {
722 printk(KERN_INFO
723 " \\--> Skipped (too many) !\n");
724 continue;
725 }
726#ifdef CONFIG_PPC32
727 /* On 32 bits, limit I/O space to 16MB */
752 if (size > 0x01000000)
753 size = 0x01000000;
728 if (range.size > 0x01000000)
729 range.size = 0x01000000;
754
755 /* 32 bits needs to map IOs here */
730
731 /* 32 bits needs to map IOs here */
756 hose->io_base_virt = ioremap(cpu_addr, size);
732 hose->io_base_virt = ioremap(range.cpu_addr,
733 range.size);
757
758 /* Expect trouble if pci_addr is not 0 */
759 if (primary)
760 isa_io_base =
761 (unsigned long)hose->io_base_virt;
762#endif /* CONFIG_PPC32 */
763 /* pci_io_size and io_base_phys always represent IO
764 * space starting at 0 so we factor in pci_addr
765 */
734
735 /* Expect trouble if pci_addr is not 0 */
736 if (primary)
737 isa_io_base =
738 (unsigned long)hose->io_base_virt;
739#endif /* CONFIG_PPC32 */
740 /* pci_io_size and io_base_phys always represent IO
741 * space starting at 0 so we factor in pci_addr
742 */
766 hose->pci_io_size = pci_addr + size;
767 hose->io_base_phys = cpu_addr - pci_addr;
743 hose->pci_io_size = range.pci_addr + range.size;
744 hose->io_base_phys = range.cpu_addr - range.pci_addr;
768
769 /* Build resource */
770 res = &hose->io_resource;
745
746 /* Build resource */
747 res = &hose->io_resource;
771 res->flags = IORESOURCE_IO;
772 res->start = pci_addr;
748 range.cpu_addr = range.pci_addr;
773 break;
749 break;
774 case 2: /* PCI Memory space */
775 case 3: /* PCI 64 bits Memory space */
750 case IORESOURCE_MEM:
776 printk(KERN_INFO
777 " MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
751 printk(KERN_INFO
752 " MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
778 cpu_addr, cpu_addr + size - 1, pci_addr,
779 (pci_space & 0x40000000) ? "Prefetch" : "");
753 range.cpu_addr, range.cpu_addr + range.size - 1,
754 range.pci_addr,
755 (range.pci_space & 0x40000000) ?
756 "Prefetch" : "");
780
781 /* We support only 3 memory ranges */
782 if (memno >= 3) {
783 printk(KERN_INFO
784 " \\--> Skipped (too many) !\n");
785 continue;
786 }
787 /* Handles ISA memory hole space here */
757
758 /* We support only 3 memory ranges */
759 if (memno >= 3) {
760 printk(KERN_INFO
761 " \\--> Skipped (too many) !\n");
762 continue;
763 }
764 /* Handles ISA memory hole space here */
788 if (pci_addr == 0) {
765 if (range.pci_addr == 0) {
789 if (primary || isa_mem_base == 0)
766 if (primary || isa_mem_base == 0)
790 isa_mem_base = cpu_addr;
791 hose->isa_mem_phys = cpu_addr;
792 hose->isa_mem_size = size;
767 isa_mem_base = range.cpu_addr;
768 hose->isa_mem_phys = range.cpu_addr;
769 hose->isa_mem_size = range.size;
793 }
794
795 /* Build resource */
770 }
771
772 /* Build resource */
796 hose->mem_offset[memno] = cpu_addr - pci_addr;
773 hose->mem_offset[memno] = range.cpu_addr -
774 range.pci_addr;
797 res = &hose->mem_resources[memno++];
775 res = &hose->mem_resources[memno++];
798 res->flags = IORESOURCE_MEM;
799 if (pci_space & 0x40000000)
800 res->flags |= IORESOURCE_PREFETCH;
801 res->start = cpu_addr;
802 break;
803 }
804 if (res != NULL) {
776 break;
777 }
778 if (res != NULL) {
805 res->name = dev->full_name;
806 res->end = res->start + size - 1;
807 res->parent = NULL;
808 res->sibling = NULL;
809 res->child = NULL;
779 of_pci_range_to_resource(&range, dev, res);
810 }
811 }
812}
813
814/* Decide whether to display the domain number in /proc */
815int pci_proc_domain(struct pci_bus *bus)
816{
817 struct pci_controller *hose = pci_bus_to_host(bus);

--- 914 unchanged lines hidden ---
780 }
781 }
782}
783
784/* Decide whether to display the domain number in /proc */
785int pci_proc_domain(struct pci_bus *bus)
786{
787 struct pci_controller *hose = pci_bus_to_host(bus);

--- 914 unchanged lines hidden ---