diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_common.c')
-rw-r--r-- | arch/sparc64/kernel/pci_common.c | 94 |
1 files changed, 89 insertions, 5 deletions
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 0d3c95df0d95..4945d700a769 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c | |||
@@ -1,7 +1,6 @@ | |||
1 | /* $Id: pci_common.c,v 1.29 2002/02/01 00:56:03 davem Exp $ | 1 | /* pci_common.c: PCI controller common support. |
2 | * pci_common.c: PCI controller common support. | ||
3 | * | 2 | * |
4 | * Copyright (C) 1999 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) |
5 | */ | 4 | */ |
6 | 5 | ||
7 | #include <linux/string.h> | 6 | #include <linux/string.h> |
@@ -16,8 +15,8 @@ | |||
16 | 15 | ||
17 | #include "pci_impl.h" | 16 | #include "pci_impl.h" |
18 | 17 | ||
19 | void pci_register_legacy_regions(struct resource *io_res, | 18 | static void pci_register_legacy_regions(struct resource *io_res, |
20 | struct resource *mem_res) | 19 | struct resource *mem_res) |
21 | { | 20 | { |
22 | struct resource *p; | 21 | struct resource *p; |
23 | 22 | ||
@@ -53,6 +52,91 @@ void pci_register_legacy_regions(struct resource *io_res, | |||
53 | request_resource(mem_res, p); | 52 | request_resource(mem_res, p); |
54 | } | 53 | } |
55 | 54 | ||
55 | static void pci_register_iommu_region(struct pci_pbm_info *pbm) | ||
56 | { | ||
57 | u32 *vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); | ||
58 | |||
59 | if (vdma) { | ||
60 | struct resource *rp = kmalloc(sizeof(*rp), GFP_KERNEL); | ||
61 | |||
62 | if (!rp) { | ||
63 | prom_printf("Cannot allocate IOMMU resource.\n"); | ||
64 | prom_halt(); | ||
65 | } | ||
66 | rp->name = "IOMMU"; | ||
67 | rp->start = pbm->mem_space.start + (unsigned long) vdma[0]; | ||
68 | rp->end = rp->start + (unsigned long) vdma[1] - 1UL; | ||
69 | rp->flags = IORESOURCE_BUSY; | ||
70 | request_resource(&pbm->mem_space, rp); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | void pci_determine_mem_io_space(struct pci_pbm_info *pbm) | ||
75 | { | ||
76 | int i, saw_mem, saw_io; | ||
77 | |||
78 | saw_mem = saw_io = 0; | ||
79 | for (i = 0; i < pbm->num_pbm_ranges; i++) { | ||
80 | struct linux_prom_pci_ranges *pr = &pbm->pbm_ranges[i]; | ||
81 | unsigned long a; | ||
82 | int type; | ||
83 | |||
84 | type = (pr->child_phys_hi >> 24) & 0x3; | ||
85 | a = (((unsigned long)pr->parent_phys_hi << 32UL) | | ||
86 | ((unsigned long)pr->parent_phys_lo << 0UL)); | ||
87 | |||
88 | switch (type) { | ||
89 | case 0: | ||
90 | /* PCI config space, 16MB */ | ||
91 | pbm->config_space = a; | ||
92 | break; | ||
93 | |||
94 | case 1: | ||
95 | /* 16-bit IO space, 16MB */ | ||
96 | pbm->io_space.start = a; | ||
97 | pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL); | ||
98 | pbm->io_space.flags = IORESOURCE_IO; | ||
99 | saw_io = 1; | ||
100 | break; | ||
101 | |||
102 | case 2: | ||
103 | /* 32-bit MEM space, 2GB */ | ||
104 | pbm->mem_space.start = a; | ||
105 | pbm->mem_space.end = a + (0x80000000UL - 1UL); | ||
106 | pbm->mem_space.flags = IORESOURCE_MEM; | ||
107 | saw_mem = 1; | ||
108 | break; | ||
109 | |||
110 | case 3: | ||
111 | /* XXX 64-bit MEM handling XXX */ | ||
112 | |||
113 | default: | ||
114 | break; | ||
115 | }; | ||
116 | } | ||
117 | |||
118 | if (!saw_io || !saw_mem) { | ||
119 | prom_printf("%s: Fatal error, missing %s PBM range.\n", | ||
120 | pbm->name, | ||
121 | (!saw_io ? "IO" : "MEM")); | ||
122 | prom_halt(); | ||
123 | } | ||
124 | |||
125 | printk("%s: PCI IO[%lx] MEM[%lx]\n", | ||
126 | pbm->name, | ||
127 | pbm->io_space.start, | ||
128 | pbm->mem_space.start); | ||
129 | |||
130 | pbm->io_space.name = pbm->mem_space.name = pbm->name; | ||
131 | |||
132 | request_resource(&ioport_resource, &pbm->io_space); | ||
133 | request_resource(&iomem_resource, &pbm->mem_space); | ||
134 | |||
135 | pci_register_legacy_regions(&pbm->io_space, | ||
136 | &pbm->mem_space); | ||
137 | pci_register_iommu_region(pbm); | ||
138 | } | ||
139 | |||
56 | /* Generic helper routines for PCI error reporting. */ | 140 | /* Generic helper routines for PCI error reporting. */ |
57 | void pci_scan_for_target_abort(struct pci_controller_info *p, | 141 | void pci_scan_for_target_abort(struct pci_controller_info *p, |
58 | struct pci_pbm_info *pbm, | 142 | struct pci_pbm_info *pbm, |