aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2008-03-25 17:44:18 -0400
committerPaul Mackerras <paulus@samba.org>2008-03-25 17:44:18 -0400
commit54f53f2b94feb72622bec7a8563fc487d9f97720 (patch)
treeab0c4e1dcadd25a00fa7a4febf41bc43b864cf73 /arch/powerpc/platforms
parentf61fb8a52cdf8b9b6a6badde84aefe58cb35d315 (diff)
parenta4083c9271e0a697278e089f2c0b9a95363ada0a (diff)
Merge branch 'linux-2.6'
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/cell/iommu.c41
-rw-r--r--arch/powerpc/platforms/cell/setup.c36
2 files changed, 61 insertions, 16 deletions
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index d6a732503ea..49fe641d434 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -802,17 +802,24 @@ static int __init cell_iommu_init_disabled(void)
802 802
803static u64 cell_iommu_get_fixed_address(struct device *dev) 803static u64 cell_iommu_get_fixed_address(struct device *dev)
804{ 804{
805 u64 cpu_addr, size, best_size, pci_addr = OF_BAD_ADDR; 805 u64 cpu_addr, size, best_size, dev_addr = OF_BAD_ADDR;
806 struct device_node *np; 806 struct device_node *np;
807 const u32 *ranges = NULL; 807 const u32 *ranges = NULL;
808 int i, len, best; 808 int i, len, best, naddr, nsize, pna, range_size;
809 809
810 np = of_node_get(dev->archdata.of_node); 810 np = of_node_get(dev->archdata.of_node);
811 while (np) { 811 while (1) {
812 naddr = of_n_addr_cells(np);
813 nsize = of_n_size_cells(np);
814 np = of_get_next_parent(np);
815 if (!np)
816 break;
817
812 ranges = of_get_property(np, "dma-ranges", &len); 818 ranges = of_get_property(np, "dma-ranges", &len);
813 if (ranges) 819
820 /* Ignore empty ranges, they imply no translation required */
821 if (ranges && len > 0)
814 break; 822 break;
815 np = of_get_next_parent(np);
816 } 823 }
817 824
818 if (!ranges) { 825 if (!ranges) {
@@ -822,15 +829,17 @@ static u64 cell_iommu_get_fixed_address(struct device *dev)
822 829
823 len /= sizeof(u32); 830 len /= sizeof(u32);
824 831
832 pna = of_n_addr_cells(np);
833 range_size = naddr + nsize + pna;
834
825 /* dma-ranges format: 835 /* dma-ranges format:
826 * 1 cell: pci space 836 * child addr : naddr cells
827 * 2 cells: pci address 837 * parent addr : pna cells
828 * 2 cells: parent address 838 * size : nsize cells
829 * 2 cells: size
830 */ 839 */
831 for (i = 0, best = -1, best_size = 0; i < len; i += 7) { 840 for (i = 0, best = -1, best_size = 0; i < len; i += range_size) {
832 cpu_addr = of_translate_dma_address(np, ranges +i + 3); 841 cpu_addr = of_translate_dma_address(np, ranges + i + naddr);
833 size = of_read_number(ranges + i + 5, 2); 842 size = of_read_number(ranges + i + naddr + pna, nsize);
834 843
835 if (cpu_addr == 0 && size > best_size) { 844 if (cpu_addr == 0 && size > best_size) {
836 best = i; 845 best = i;
@@ -838,15 +847,15 @@ static u64 cell_iommu_get_fixed_address(struct device *dev)
838 } 847 }
839 } 848 }
840 849
841 if (best >= 0) 850 if (best >= 0) {
842 pci_addr = of_read_number(ranges + best + 1, 2); 851 dev_addr = of_read_number(ranges + best, naddr);
843 else 852 } else
844 dev_dbg(dev, "iommu: no suitable range found!\n"); 853 dev_dbg(dev, "iommu: no suitable range found!\n");
845 854
846out: 855out:
847 of_node_put(np); 856 of_node_put(np);
848 857
849 return pci_addr; 858 return dev_addr;
850} 859}
851 860
852static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask) 861static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask)
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index dda34650cb0..5c531e8f9f6 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -81,6 +81,42 @@ static void cell_progress(char *s, unsigned short hex)
81 printk("*** %04x : %s\n", hex, s ? s : ""); 81 printk("*** %04x : %s\n", hex, s ? s : "");
82} 82}
83 83
84static void cell_fixup_pcie_rootcomplex(struct pci_dev *dev)
85{
86 struct pci_controller *hose;
87 const char *s;
88 int i;
89
90 if (!machine_is(cell))
91 return;
92
93 /* We're searching for a direct child of the PHB */
94 if (dev->bus->self != NULL || dev->devfn != 0)
95 return;
96
97 hose = pci_bus_to_host(dev->bus);
98 if (hose == NULL)
99 return;
100
101 /* Only on PCIE */
102 if (!of_device_is_compatible(hose->dn, "pciex"))
103 return;
104
105 /* And only on axon */
106 s = of_get_property(hose->dn, "model", NULL);
107 if (!s || strcmp(s, "Axon") != 0)
108 return;
109
110 for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
111 dev->resource[i].start = dev->resource[i].end = 0;
112 dev->resource[i].flags = 0;
113 }
114
115 printk(KERN_DEBUG "PCI: Hiding resources on Axon PCIE RC %s\n",
116 pci_name(dev));
117}
118DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, cell_fixup_pcie_rootcomplex);
119
84static int __init cell_publish_devices(void) 120static int __init cell_publish_devices(void)
85{ 121{
86 int node; 122 int node;