diff options
Diffstat (limited to 'arch/ppc/kernel/pci.c')
-rw-r--r-- | arch/ppc/kernel/pci.c | 396 |
1 files changed, 0 insertions, 396 deletions
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 04d04c5bfdd0..809673a36f7a 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c | |||
@@ -46,9 +46,6 @@ static void pcibios_fixup_resources(struct pci_dev* dev); | |||
46 | static void fixup_broken_pcnet32(struct pci_dev* dev); | 46 | static void fixup_broken_pcnet32(struct pci_dev* dev); |
47 | static int reparent_resources(struct resource *parent, struct resource *res); | 47 | static int reparent_resources(struct resource *parent, struct resource *res); |
48 | static void fixup_cpc710_pci64(struct pci_dev* dev); | 48 | static void fixup_cpc710_pci64(struct pci_dev* dev); |
49 | #ifdef CONFIG_PPC_OF | ||
50 | static u8* pci_to_OF_bus_map; | ||
51 | #endif | ||
52 | 49 | ||
53 | /* By default, we don't re-assign bus numbers. | 50 | /* By default, we don't re-assign bus numbers. |
54 | */ | 51 | */ |
@@ -625,406 +622,13 @@ pcibios_alloc_controller(void) | |||
625 | return hose; | 622 | return hose; |
626 | } | 623 | } |
627 | 624 | ||
628 | #ifdef CONFIG_PPC_OF | ||
629 | /* | ||
630 | * Functions below are used on OpenFirmware machines. | ||
631 | */ | ||
632 | static void | ||
633 | make_one_node_map(struct device_node* node, u8 pci_bus) | ||
634 | { | ||
635 | int *bus_range; | ||
636 | int len; | ||
637 | |||
638 | if (pci_bus >= pci_bus_count) | ||
639 | return; | ||
640 | bus_range = (int *) get_property(node, "bus-range", &len); | ||
641 | if (bus_range == NULL || len < 2 * sizeof(int)) { | ||
642 | printk(KERN_WARNING "Can't get bus-range for %s, " | ||
643 | "assuming it starts at 0\n", node->full_name); | ||
644 | pci_to_OF_bus_map[pci_bus] = 0; | ||
645 | } else | ||
646 | pci_to_OF_bus_map[pci_bus] = bus_range[0]; | ||
647 | |||
648 | for (node=node->child; node != 0;node = node->sibling) { | ||
649 | struct pci_dev* dev; | ||
650 | unsigned int *class_code, *reg; | ||
651 | |||
652 | class_code = (unsigned int *) get_property(node, "class-code", NULL); | ||
653 | if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && | ||
654 | (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) | ||
655 | continue; | ||
656 | reg = (unsigned int *)get_property(node, "reg", NULL); | ||
657 | if (!reg) | ||
658 | continue; | ||
659 | dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff)); | ||
660 | if (!dev || !dev->subordinate) | ||
661 | continue; | ||
662 | make_one_node_map(node, dev->subordinate->number); | ||
663 | } | ||
664 | } | ||
665 | |||
666 | void | ||
667 | pcibios_make_OF_bus_map(void) | ||
668 | { | ||
669 | int i; | ||
670 | struct pci_controller* hose; | ||
671 | u8* of_prop_map; | ||
672 | |||
673 | pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL); | ||
674 | if (!pci_to_OF_bus_map) { | ||
675 | printk(KERN_ERR "Can't allocate OF bus map !\n"); | ||
676 | return; | ||
677 | } | ||
678 | |||
679 | /* We fill the bus map with invalid values, that helps | ||
680 | * debugging. | ||
681 | */ | ||
682 | for (i=0; i<pci_bus_count; i++) | ||
683 | pci_to_OF_bus_map[i] = 0xff; | ||
684 | |||
685 | /* For each hose, we begin searching bridges */ | ||
686 | for(hose=hose_head; hose; hose=hose->next) { | ||
687 | struct device_node* node; | ||
688 | node = (struct device_node *)hose->arch_data; | ||
689 | if (!node) | ||
690 | continue; | ||
691 | make_one_node_map(node, hose->first_busno); | ||
692 | } | ||
693 | of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL); | ||
694 | if (of_prop_map) | ||
695 | memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count); | ||
696 | #ifdef DEBUG | ||
697 | printk("PCI->OF bus map:\n"); | ||
698 | for (i=0; i<pci_bus_count; i++) { | ||
699 | if (pci_to_OF_bus_map[i] == 0xff) | ||
700 | continue; | ||
701 | printk("%d -> %d\n", i, pci_to_OF_bus_map[i]); | ||
702 | } | ||
703 | #endif | ||
704 | } | ||
705 | |||
706 | typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data); | ||
707 | |||
708 | static struct device_node* | ||
709 | scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data) | ||
710 | { | ||
711 | struct device_node* sub_node; | ||
712 | |||
713 | for (; node != 0;node = node->sibling) { | ||
714 | unsigned int *class_code; | ||
715 | |||
716 | if (filter(node, data)) | ||
717 | return node; | ||
718 | |||
719 | /* For PCI<->PCI bridges or CardBus bridges, we go down | ||
720 | * Note: some OFs create a parent node "multifunc-device" as | ||
721 | * a fake root for all functions of a multi-function device, | ||
722 | * we go down them as well. | ||
723 | */ | ||
724 | class_code = (unsigned int *) get_property(node, "class-code", NULL); | ||
725 | if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && | ||
726 | (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) && | ||
727 | strcmp(node->name, "multifunc-device")) | ||
728 | continue; | ||
729 | sub_node = scan_OF_pci_childs(node->child, filter, data); | ||
730 | if (sub_node) | ||
731 | return sub_node; | ||
732 | } | ||
733 | return NULL; | ||
734 | } | ||
735 | |||
736 | static int | ||
737 | scan_OF_pci_childs_iterator(struct device_node* node, void* data) | ||
738 | { | ||
739 | unsigned int *reg; | ||
740 | u8* fdata = (u8*)data; | ||
741 | |||
742 | reg = (unsigned int *) get_property(node, "reg", NULL); | ||
743 | if (reg && ((reg[0] >> 8) & 0xff) == fdata[1] | ||
744 | && ((reg[0] >> 16) & 0xff) == fdata[0]) | ||
745 | return 1; | ||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | static struct device_node* | ||
750 | scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn) | ||
751 | { | ||
752 | u8 filter_data[2] = {bus, dev_fn}; | ||
753 | |||
754 | return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data); | ||
755 | } | ||
756 | |||
757 | /* | ||
758 | * Scans the OF tree for a device node matching a PCI device | ||
759 | */ | ||
760 | struct device_node * | ||
761 | pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) | ||
762 | { | ||
763 | struct pci_controller *hose; | ||
764 | struct device_node *node; | ||
765 | int busnr; | ||
766 | |||
767 | if (!have_of) | ||
768 | return NULL; | ||
769 | |||
770 | /* Lookup the hose */ | ||
771 | busnr = bus->number; | ||
772 | hose = pci_bus_to_hose(busnr); | ||
773 | if (!hose) | ||
774 | return NULL; | ||
775 | |||
776 | /* Check it has an OF node associated */ | ||
777 | node = (struct device_node *) hose->arch_data; | ||
778 | if (!node) | ||
779 | return NULL; | ||
780 | |||
781 | /* Fixup bus number according to what OF think it is. */ | ||
782 | if (pci_to_OF_bus_map) | ||
783 | busnr = pci_to_OF_bus_map[busnr]; | ||
784 | if (busnr == 0xff) | ||
785 | return NULL; | ||
786 | |||
787 | /* Now, lookup childs of the hose */ | ||
788 | return scan_OF_childs_for_device(node->child, busnr, devfn); | ||
789 | } | ||
790 | EXPORT_SYMBOL(pci_busdev_to_OF_node); | ||
791 | |||
792 | struct device_node* | ||
793 | pci_device_to_OF_node(struct pci_dev *dev) | ||
794 | { | ||
795 | return pci_busdev_to_OF_node(dev->bus, dev->devfn); | ||
796 | } | ||
797 | EXPORT_SYMBOL(pci_device_to_OF_node); | ||
798 | |||
799 | /* This routine is meant to be used early during boot, when the | ||
800 | * PCI bus numbers have not yet been assigned, and you need to | ||
801 | * issue PCI config cycles to an OF device. | ||
802 | * It could also be used to "fix" RTAS config cycles if you want | ||
803 | * to set pci_assign_all_buses to 1 and still use RTAS for PCI | ||
804 | * config cycles. | ||
805 | */ | ||
806 | struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | ||
807 | { | ||
808 | if (!have_of) | ||
809 | return NULL; | ||
810 | while(node) { | ||
811 | struct pci_controller* hose; | ||
812 | for (hose=hose_head;hose;hose=hose->next) | ||
813 | if (hose->arch_data == node) | ||
814 | return hose; | ||
815 | node=node->parent; | ||
816 | } | ||
817 | return NULL; | ||
818 | } | ||
819 | |||
820 | static int | ||
821 | find_OF_pci_device_filter(struct device_node* node, void* data) | ||
822 | { | ||
823 | return ((void *)node == data); | ||
824 | } | ||
825 | |||
826 | /* | ||
827 | * Returns the PCI device matching a given OF node | ||
828 | */ | ||
829 | int | ||
830 | pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn) | ||
831 | { | ||
832 | unsigned int *reg; | ||
833 | struct pci_controller* hose; | ||
834 | struct pci_dev* dev = NULL; | ||
835 | |||
836 | if (!have_of) | ||
837 | return -ENODEV; | ||
838 | /* Make sure it's really a PCI device */ | ||
839 | hose = pci_find_hose_for_OF_device(node); | ||
840 | if (!hose || !hose->arch_data) | ||
841 | return -ENODEV; | ||
842 | if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child, | ||
843 | find_OF_pci_device_filter, (void *)node)) | ||
844 | return -ENODEV; | ||
845 | reg = (unsigned int *) get_property(node, "reg", NULL); | ||
846 | if (!reg) | ||
847 | return -ENODEV; | ||
848 | *bus = (reg[0] >> 16) & 0xff; | ||
849 | *devfn = ((reg[0] >> 8) & 0xff); | ||
850 | |||
851 | /* Ok, here we need some tweak. If we have already renumbered | ||
852 | * all busses, we can't rely on the OF bus number any more. | ||
853 | * the pci_to_OF_bus_map is not enough as several PCI busses | ||
854 | * may match the same OF bus number. | ||
855 | */ | ||
856 | if (!pci_to_OF_bus_map) | ||
857 | return 0; | ||
858 | |||
859 | for_each_pci_dev(dev) | ||
860 | if (pci_to_OF_bus_map[dev->bus->number] == *bus && | ||
861 | dev->devfn == *devfn) { | ||
862 | *bus = dev->bus->number; | ||
863 | pci_dev_put(dev); | ||
864 | return 0; | ||
865 | } | ||
866 | |||
867 | return -ENODEV; | ||
868 | } | ||
869 | EXPORT_SYMBOL(pci_device_from_OF_node); | ||
870 | |||
871 | void __init | ||
872 | pci_process_bridge_OF_ranges(struct pci_controller *hose, | ||
873 | struct device_node *dev, int primary) | ||
874 | { | ||
875 | static unsigned int static_lc_ranges[256] __initdata; | ||
876 | unsigned int *dt_ranges, *lc_ranges, *ranges, *prev; | ||
877 | unsigned int size; | ||
878 | int rlen = 0, orig_rlen; | ||
879 | int memno = 0; | ||
880 | struct resource *res; | ||
881 | int np, na = prom_n_addr_cells(dev); | ||
882 | np = na + 5; | ||
883 | |||
884 | /* First we try to merge ranges to fix a problem with some pmacs | ||
885 | * that can have more than 3 ranges, fortunately using contiguous | ||
886 | * addresses -- BenH | ||
887 | */ | ||
888 | dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen); | ||
889 | if (!dt_ranges) | ||
890 | return; | ||
891 | /* Sanity check, though hopefully that never happens */ | ||
892 | if (rlen > sizeof(static_lc_ranges)) { | ||
893 | printk(KERN_WARNING "OF ranges property too large !\n"); | ||
894 | rlen = sizeof(static_lc_ranges); | ||
895 | } | ||
896 | lc_ranges = static_lc_ranges; | ||
897 | memcpy(lc_ranges, dt_ranges, rlen); | ||
898 | orig_rlen = rlen; | ||
899 | |||
900 | /* Let's work on a copy of the "ranges" property instead of damaging | ||
901 | * the device-tree image in memory | ||
902 | */ | ||
903 | ranges = lc_ranges; | ||
904 | prev = NULL; | ||
905 | while ((rlen -= np * sizeof(unsigned int)) >= 0) { | ||
906 | if (prev) { | ||
907 | if (prev[0] == ranges[0] && prev[1] == ranges[1] && | ||
908 | (prev[2] + prev[na+4]) == ranges[2] && | ||
909 | (prev[na+2] + prev[na+4]) == ranges[na+2]) { | ||
910 | prev[na+4] += ranges[na+4]; | ||
911 | ranges[0] = 0; | ||
912 | ranges += np; | ||
913 | continue; | ||
914 | } | ||
915 | } | ||
916 | prev = ranges; | ||
917 | ranges += np; | ||
918 | } | ||
919 | |||
920 | /* | ||
921 | * The ranges property is laid out as an array of elements, | ||
922 | * each of which comprises: | ||
923 | * cells 0 - 2: a PCI address | ||
924 | * cells 3 or 3+4: a CPU physical address | ||
925 | * (size depending on dev->n_addr_cells) | ||
926 | * cells 4+5 or 5+6: the size of the range | ||
927 | */ | ||
928 | ranges = lc_ranges; | ||
929 | rlen = orig_rlen; | ||
930 | while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) { | ||
931 | res = NULL; | ||
932 | size = ranges[na+4]; | ||
933 | switch ((ranges[0] >> 24) & 0x3) { | ||
934 | case 1: /* I/O space */ | ||
935 | if (ranges[2] != 0) | ||
936 | break; | ||
937 | hose->io_base_phys = ranges[na+2]; | ||
938 | /* limit I/O space to 16MB */ | ||
939 | if (size > 0x01000000) | ||
940 | size = 0x01000000; | ||
941 | hose->io_base_virt = ioremap(ranges[na+2], size); | ||
942 | if (primary) | ||
943 | isa_io_base = (unsigned long) hose->io_base_virt; | ||
944 | res = &hose->io_resource; | ||
945 | res->flags = IORESOURCE_IO; | ||
946 | res->start = ranges[2]; | ||
947 | DBG("PCI: IO 0x%lx -> 0x%lx\n", | ||
948 | res->start, res->start + size - 1); | ||
949 | break; | ||
950 | case 2: /* memory space */ | ||
951 | memno = 0; | ||
952 | if (ranges[1] == 0 && ranges[2] == 0 | ||
953 | && ranges[na+4] <= (16 << 20)) { | ||
954 | /* 1st 16MB, i.e. ISA memory area */ | ||
955 | if (primary) | ||
956 | isa_mem_base = ranges[na+2]; | ||
957 | memno = 1; | ||
958 | } | ||
959 | while (memno < 3 && hose->mem_resources[memno].flags) | ||
960 | ++memno; | ||
961 | if (memno == 0) | ||
962 | hose->pci_mem_offset = ranges[na+2] - ranges[2]; | ||
963 | if (memno < 3) { | ||
964 | res = &hose->mem_resources[memno]; | ||
965 | res->flags = IORESOURCE_MEM; | ||
966 | if(ranges[0] & 0x40000000) | ||
967 | res->flags |= IORESOURCE_PREFETCH; | ||
968 | res->start = ranges[na+2]; | ||
969 | DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno, | ||
970 | res->start, res->start + size - 1); | ||
971 | } | ||
972 | break; | ||
973 | } | ||
974 | if (res != NULL) { | ||
975 | res->name = dev->full_name; | ||
976 | res->end = res->start + size - 1; | ||
977 | res->parent = NULL; | ||
978 | res->sibling = NULL; | ||
979 | res->child = NULL; | ||
980 | } | ||
981 | ranges += np; | ||
982 | } | ||
983 | } | ||
984 | |||
985 | /* We create the "pci-OF-bus-map" property now so it appears in the | ||
986 | * /proc device tree | ||
987 | */ | ||
988 | void __init | ||
989 | pci_create_OF_bus_map(void) | ||
990 | { | ||
991 | struct property* of_prop; | ||
992 | |||
993 | of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256); | ||
994 | if (of_prop && find_path_device("/")) { | ||
995 | memset(of_prop, -1, sizeof(struct property) + 256); | ||
996 | of_prop->name = "pci-OF-bus-map"; | ||
997 | of_prop->length = 256; | ||
998 | of_prop->value = (unsigned char *)&of_prop[1]; | ||
999 | prom_add_property(find_path_device("/"), of_prop); | ||
1000 | } | ||
1001 | } | ||
1002 | |||
1003 | static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) | ||
1004 | { | ||
1005 | struct pci_dev *pdev; | ||
1006 | struct device_node *np; | ||
1007 | |||
1008 | pdev = to_pci_dev (dev); | ||
1009 | np = pci_device_to_OF_node(pdev); | ||
1010 | if (np == NULL || np->full_name == NULL) | ||
1011 | return 0; | ||
1012 | return sprintf(buf, "%s", np->full_name); | ||
1013 | } | ||
1014 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||
1015 | |||
1016 | #else /* CONFIG_PPC_OF */ | ||
1017 | void pcibios_make_OF_bus_map(void) | 625 | void pcibios_make_OF_bus_map(void) |
1018 | { | 626 | { |
1019 | } | 627 | } |
1020 | #endif /* CONFIG_PPC_OF */ | ||
1021 | 628 | ||
1022 | /* Add sysfs properties */ | 629 | /* Add sysfs properties */ |
1023 | void pcibios_add_platform_entries(struct pci_dev *pdev) | 630 | void pcibios_add_platform_entries(struct pci_dev *pdev) |
1024 | { | 631 | { |
1025 | #ifdef CONFIG_PPC_OF | ||
1026 | device_create_file(&pdev->dev, &dev_attr_devspec); | ||
1027 | #endif /* CONFIG_PPC_OF */ | ||
1028 | } | 632 | } |
1029 | 633 | ||
1030 | 634 | ||