aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/prom_parse.c
diff options
context:
space:
mode:
authorAndy Fleming <afleming@freescale.com>2006-10-16 17:03:33 -0400
committerPaul Mackerras <paulus@samba.org>2006-10-24 01:01:27 -0400
commit83efafb301bc79a32799ca854fb590e82c4396e9 (patch)
treec6047820e93f8ba6633f989e2d00558be94fbb54 /arch/powerpc/kernel/prom_parse.c
parent0cfcccb4687862a34eb609d16e75b39b6cb54c80 (diff)
[POWERPC] Fix up the OF functions to only do PCI stuff if PCI is actually configured
The original problem that inspired this patch was solved quite some time ago (Turning off PCI didn't work), but this patch neatens things up a little (I think), by putting all the PCI stuff inside a single CONFIG_PCI block. It also removes the OF PCI bus matching entries if CONFIG_PCI is off. Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/prom_parse.c')
-rw-r--r--arch/powerpc/kernel/prom_parse.c288
1 files changed, 148 insertions, 140 deletions
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 603dff3ad62a..346fb7bf9a05 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -25,6 +25,12 @@
25#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ 25#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
26 (ns) > 0) 26 (ns) > 0)
27 27
28static struct of_bus *of_match_bus(struct device_node *np);
29static int __of_address_to_resource(struct device_node *dev,
30 const u32 *addrp, u64 size, unsigned int flags,
31 struct resource *r);
32
33
28/* Debug utility */ 34/* Debug utility */
29#ifdef DEBUG 35#ifdef DEBUG
30static void of_dump_addr(const char *s, const u32 *addr, int na) 36static void of_dump_addr(const char *s, const u32 *addr, int na)
@@ -101,6 +107,7 @@ static unsigned int of_bus_default_get_flags(const u32 *addr)
101} 107}
102 108
103 109
110#ifdef CONFIG_PCI
104/* 111/*
105 * PCI bus specific translator 112 * PCI bus specific translator
106 */ 113 */
@@ -162,6 +169,145 @@ static unsigned int of_bus_pci_get_flags(const u32 *addr)
162 return flags; 169 return flags;
163} 170}
164 171
172const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
173 unsigned int *flags)
174{
175 const u32 *prop;
176 unsigned int psize;
177 struct device_node *parent;
178 struct of_bus *bus;
179 int onesize, i, na, ns;
180
181 /* Get parent & match bus type */
182 parent = of_get_parent(dev);
183 if (parent == NULL)
184 return NULL;
185 bus = of_match_bus(parent);
186 if (strcmp(bus->name, "pci")) {
187 of_node_put(parent);
188 return NULL;
189 }
190 bus->count_cells(dev, &na, &ns);
191 of_node_put(parent);
192 if (!OF_CHECK_COUNTS(na, ns))
193 return NULL;
194
195 /* Get "reg" or "assigned-addresses" property */
196 prop = get_property(dev, bus->addresses, &psize);
197 if (prop == NULL)
198 return NULL;
199 psize /= 4;
200
201 onesize = na + ns;
202 for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
203 if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
204 if (size)
205 *size = of_read_number(prop + na, ns);
206 if (flags)
207 *flags = bus->get_flags(prop);
208 return prop;
209 }
210 return NULL;
211}
212EXPORT_SYMBOL(of_get_pci_address);
213
214int of_pci_address_to_resource(struct device_node *dev, int bar,
215 struct resource *r)
216{
217 const u32 *addrp;
218 u64 size;
219 unsigned int flags;
220
221 addrp = of_get_pci_address(dev, bar, &size, &flags);
222 if (addrp == NULL)
223 return -EINVAL;
224 return __of_address_to_resource(dev, addrp, size, flags, r);
225}
226EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
227
228static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
229{
230 return (((pin - 1) + slot) % 4) + 1;
231}
232
233int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
234{
235 struct device_node *dn, *ppnode;
236 struct pci_dev *ppdev;
237 u32 lspec;
238 u32 laddr[3];
239 u8 pin;
240 int rc;
241
242 /* Check if we have a device node, if yes, fallback to standard OF
243 * parsing
244 */
245 dn = pci_device_to_OF_node(pdev);
246 if (dn)
247 return of_irq_map_one(dn, 0, out_irq);
248
249 /* Ok, we don't, time to have fun. Let's start by building up an
250 * interrupt spec. we assume #interrupt-cells is 1, which is standard
251 * for PCI. If you do different, then don't use that routine.
252 */
253 rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
254 if (rc != 0)
255 return rc;
256 /* No pin, exit */
257 if (pin == 0)
258 return -ENODEV;
259
260 /* Now we walk up the PCI tree */
261 lspec = pin;
262 for (;;) {
263 /* Get the pci_dev of our parent */
264 ppdev = pdev->bus->self;
265
266 /* Ouch, it's a host bridge... */
267 if (ppdev == NULL) {
268#ifdef CONFIG_PPC64
269 ppnode = pci_bus_to_OF_node(pdev->bus);
270#else
271 struct pci_controller *host;
272 host = pci_bus_to_host(pdev->bus);
273 ppnode = host ? host->arch_data : NULL;
274#endif
275 /* No node for host bridge ? give up */
276 if (ppnode == NULL)
277 return -EINVAL;
278 } else
279 /* We found a P2P bridge, check if it has a node */
280 ppnode = pci_device_to_OF_node(ppdev);
281
282 /* Ok, we have found a parent with a device-node, hand over to
283 * the OF parsing code.
284 * We build a unit address from the linux device to be used for
285 * resolution. Note that we use the linux bus number which may
286 * not match your firmware bus numbering.
287 * Fortunately, in most cases, interrupt-map-mask doesn't include
288 * the bus number as part of the matching.
289 * You should still be careful about that though if you intend
290 * to rely on this function (you ship a firmware that doesn't
291 * create device nodes for all PCI devices).
292 */
293 if (ppnode)
294 break;
295
296 /* We can only get here if we hit a P2P bridge with no node,
297 * let's do standard swizzling and try again
298 */
299 lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
300 pdev = ppdev;
301 }
302
303 laddr[0] = (pdev->bus->number << 16)
304 | (pdev->devfn << 8);
305 laddr[1] = laddr[2] = 0;
306 return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
307}
308EXPORT_SYMBOL_GPL(of_irq_map_pci);
309#endif /* CONFIG_PCI */
310
165/* 311/*
166 * ISA bus specific translator 312 * ISA bus specific translator
167 */ 313 */
@@ -223,6 +369,7 @@ static unsigned int of_bus_isa_get_flags(const u32 *addr)
223 */ 369 */
224 370
225static struct of_bus of_busses[] = { 371static struct of_bus of_busses[] = {
372#ifdef CONFIG_PCI
226 /* PCI */ 373 /* PCI */
227 { 374 {
228 .name = "pci", 375 .name = "pci",
@@ -233,6 +380,7 @@ static struct of_bus of_busses[] = {
233 .translate = of_bus_pci_translate, 380 .translate = of_bus_pci_translate,
234 .get_flags = of_bus_pci_get_flags, 381 .get_flags = of_bus_pci_get_flags,
235 }, 382 },
383#endif /* CONFIG_PCI */
236 /* ISA */ 384 /* ISA */
237 { 385 {
238 .name = "isa", 386 .name = "isa",
@@ -445,48 +593,6 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
445} 593}
446EXPORT_SYMBOL(of_get_address); 594EXPORT_SYMBOL(of_get_address);
447 595
448const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
449 unsigned int *flags)
450{
451 const u32 *prop;
452 unsigned int psize;
453 struct device_node *parent;
454 struct of_bus *bus;
455 int onesize, i, na, ns;
456
457 /* Get parent & match bus type */
458 parent = of_get_parent(dev);
459 if (parent == NULL)
460 return NULL;
461 bus = of_match_bus(parent);
462 if (strcmp(bus->name, "pci")) {
463 of_node_put(parent);
464 return NULL;
465 }
466 bus->count_cells(dev, &na, &ns);
467 of_node_put(parent);
468 if (!OF_CHECK_COUNTS(na, ns))
469 return NULL;
470
471 /* Get "reg" or "assigned-addresses" property */
472 prop = get_property(dev, bus->addresses, &psize);
473 if (prop == NULL)
474 return NULL;
475 psize /= 4;
476
477 onesize = na + ns;
478 for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
479 if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
480 if (size)
481 *size = of_read_number(prop + na, ns);
482 if (flags)
483 *flags = bus->get_flags(prop);
484 return prop;
485 }
486 return NULL;
487}
488EXPORT_SYMBOL(of_get_pci_address);
489
490static int __of_address_to_resource(struct device_node *dev, const u32 *addrp, 596static int __of_address_to_resource(struct device_node *dev, const u32 *addrp,
491 u64 size, unsigned int flags, 597 u64 size, unsigned int flags,
492 struct resource *r) 598 struct resource *r)
@@ -529,20 +635,6 @@ int of_address_to_resource(struct device_node *dev, int index,
529} 635}
530EXPORT_SYMBOL_GPL(of_address_to_resource); 636EXPORT_SYMBOL_GPL(of_address_to_resource);
531 637
532int of_pci_address_to_resource(struct device_node *dev, int bar,
533 struct resource *r)
534{
535 const u32 *addrp;
536 u64 size;
537 unsigned int flags;
538
539 addrp = of_get_pci_address(dev, bar, &size, &flags);
540 if (addrp == NULL)
541 return -EINVAL;
542 return __of_address_to_resource(dev, addrp, size, flags, r);
543}
544EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
545
546void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, 638void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
547 unsigned long *busno, unsigned long *phys, unsigned long *size) 639 unsigned long *busno, unsigned long *phys, unsigned long *size)
548{ 640{
@@ -898,87 +990,3 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
898 return res; 990 return res;
899} 991}
900EXPORT_SYMBOL_GPL(of_irq_map_one); 992EXPORT_SYMBOL_GPL(of_irq_map_one);
901
902#ifdef CONFIG_PCI
903static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
904{
905 return (((pin - 1) + slot) % 4) + 1;
906}
907
908int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
909{
910 struct device_node *dn, *ppnode;
911 struct pci_dev *ppdev;
912 u32 lspec;
913 u32 laddr[3];
914 u8 pin;
915 int rc;
916
917 /* Check if we have a device node, if yes, fallback to standard OF
918 * parsing
919 */
920 dn = pci_device_to_OF_node(pdev);
921 if (dn)
922 return of_irq_map_one(dn, 0, out_irq);
923
924 /* Ok, we don't, time to have fun. Let's start by building up an
925 * interrupt spec. we assume #interrupt-cells is 1, which is standard
926 * for PCI. If you do different, then don't use that routine.
927 */
928 rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
929 if (rc != 0)
930 return rc;
931 /* No pin, exit */
932 if (pin == 0)
933 return -ENODEV;
934
935 /* Now we walk up the PCI tree */
936 lspec = pin;
937 for (;;) {
938 /* Get the pci_dev of our parent */
939 ppdev = pdev->bus->self;
940
941 /* Ouch, it's a host bridge... */
942 if (ppdev == NULL) {
943#ifdef CONFIG_PPC64
944 ppnode = pci_bus_to_OF_node(pdev->bus);
945#else
946 struct pci_controller *host;
947 host = pci_bus_to_host(pdev->bus);
948 ppnode = host ? host->arch_data : NULL;
949#endif
950 /* No node for host bridge ? give up */
951 if (ppnode == NULL)
952 return -EINVAL;
953 } else
954 /* We found a P2P bridge, check if it has a node */
955 ppnode = pci_device_to_OF_node(ppdev);
956
957 /* Ok, we have found a parent with a device-node, hand over to
958 * the OF parsing code.
959 * We build a unit address from the linux device to be used for
960 * resolution. Note that we use the linux bus number which may
961 * not match your firmware bus numbering.
962 * Fortunately, in most cases, interrupt-map-mask doesn't include
963 * the bus number as part of the matching.
964 * You should still be careful about that though if you intend
965 * to rely on this function (you ship a firmware that doesn't
966 * create device nodes for all PCI devices).
967 */
968 if (ppnode)
969 break;
970
971 /* We can only get here if we hit a P2P bridge with no node,
972 * let's do standard swizzling and try again
973 */
974 lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
975 pdev = ppdev;
976 }
977
978 laddr[0] = (pdev->bus->number << 16)
979 | (pdev->devfn << 8);
980 laddr[1] = laddr[2] = 0;
981 return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
982}
983EXPORT_SYMBOL_GPL(of_irq_map_pci);
984#endif /* CONFIG_PCI */