diff options
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/btext.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 24 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom.c | 424 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/rtas_pci.c | 49 |
5 files changed, 46 insertions, 456 deletions
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 5de0d80ca2f2..6223d39177cb 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c | |||
@@ -211,8 +211,6 @@ int __init btext_find_display(int allow_nonstdout) | |||
211 | struct device_node *np = NULL; | 211 | struct device_node *np = NULL; |
212 | int rc = -ENODEV; | 212 | int rc = -ENODEV; |
213 | 213 | ||
214 | printk("trying to initialize btext ...\n"); | ||
215 | |||
216 | name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); | 214 | name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); |
217 | if (name != NULL) { | 215 | if (name != NULL) { |
218 | np = of_find_node_by_path(name); | 216 | np = of_find_node_by_path(name); |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 4eb93fc1eef2..523f35087e81 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -896,6 +896,25 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, | |||
896 | unsigned long phb_io_base_phys, | 896 | unsigned long phb_io_base_phys, |
897 | void __iomem * phb_io_base_virt) | 897 | void __iomem * phb_io_base_virt) |
898 | { | 898 | { |
899 | /* Remove these asap */ | ||
900 | |||
901 | struct pci_address { | ||
902 | u32 a_hi; | ||
903 | u32 a_mid; | ||
904 | u32 a_lo; | ||
905 | }; | ||
906 | |||
907 | struct isa_address { | ||
908 | u32 a_hi; | ||
909 | u32 a_lo; | ||
910 | }; | ||
911 | |||
912 | struct isa_range { | ||
913 | struct isa_address isa_addr; | ||
914 | struct pci_address pci_addr; | ||
915 | unsigned int size; | ||
916 | }; | ||
917 | |||
899 | struct isa_range *range; | 918 | struct isa_range *range; |
900 | unsigned long pci_addr; | 919 | unsigned long pci_addr; |
901 | unsigned int isa_addr; | 920 | unsigned int isa_addr; |
@@ -1330,8 +1349,9 @@ unsigned int pci_address_to_pio(phys_addr_t address) | |||
1330 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | 1349 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
1331 | if (address >= hose->io_base_phys && | 1350 | if (address >= hose->io_base_phys && |
1332 | address < (hose->io_base_phys + hose->pci_io_size)) | 1351 | address < (hose->io_base_phys + hose->pci_io_size)) |
1333 | return (unsigned int)hose->io_base_virt + | 1352 | return (unsigned int) |
1334 | (address - hose->io_base_phys); | 1353 | ((unsigned long)hose->io_base_virt + |
1354 | (address - hose->io_base_phys)); | ||
1335 | } | 1355 | } |
1336 | return (unsigned int)-1; | 1356 | return (unsigned int)-1; |
1337 | } | 1357 | } |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 7e798d5b03b4..1b97e13657e5 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -57,21 +57,6 @@ | |||
57 | #define DBG(fmt...) | 57 | #define DBG(fmt...) |
58 | #endif | 58 | #endif |
59 | 59 | ||
60 | struct pci_reg_property { | ||
61 | struct pci_address addr; | ||
62 | u32 size_hi; | ||
63 | u32 size_lo; | ||
64 | }; | ||
65 | |||
66 | struct isa_reg_property { | ||
67 | u32 space; | ||
68 | u32 address; | ||
69 | u32 size; | ||
70 | }; | ||
71 | |||
72 | |||
73 | typedef int interpret_func(struct device_node *, unsigned long *, | ||
74 | int, int, int); | ||
75 | 60 | ||
76 | static int __initdata dt_root_addr_cells; | 61 | static int __initdata dt_root_addr_cells; |
77 | static int __initdata dt_root_size_cells; | 62 | static int __initdata dt_root_size_cells; |
@@ -410,237 +395,19 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
410 | return 0; | 395 | return 0; |
411 | } | 396 | } |
412 | 397 | ||
413 | static int __devinit interpret_pci_props(struct device_node *np, | ||
414 | unsigned long *mem_start, | ||
415 | int naddrc, int nsizec, | ||
416 | int measure_only) | ||
417 | { | ||
418 | struct address_range *adr; | ||
419 | struct pci_reg_property *pci_addrs; | ||
420 | int i, l, n_addrs; | ||
421 | |||
422 | pci_addrs = (struct pci_reg_property *) | ||
423 | get_property(np, "assigned-addresses", &l); | ||
424 | if (!pci_addrs) | ||
425 | return 0; | ||
426 | |||
427 | n_addrs = l / sizeof(*pci_addrs); | ||
428 | |||
429 | adr = prom_alloc(n_addrs * sizeof(*adr), mem_start); | ||
430 | if (!adr) | ||
431 | return -ENOMEM; | ||
432 | |||
433 | if (measure_only) | ||
434 | return 0; | ||
435 | |||
436 | np->addrs = adr; | ||
437 | np->n_addrs = n_addrs; | ||
438 | |||
439 | for (i = 0; i < n_addrs; i++) { | ||
440 | adr[i].space = pci_addrs[i].addr.a_hi; | ||
441 | adr[i].address = pci_addrs[i].addr.a_lo | | ||
442 | ((u64)pci_addrs[i].addr.a_mid << 32); | ||
443 | adr[i].size = pci_addrs[i].size_lo; | ||
444 | } | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | static int __init interpret_dbdma_props(struct device_node *np, | ||
450 | unsigned long *mem_start, | ||
451 | int naddrc, int nsizec, | ||
452 | int measure_only) | ||
453 | { | ||
454 | struct reg_property32 *rp; | ||
455 | struct address_range *adr; | ||
456 | unsigned long base_address; | ||
457 | int i, l; | ||
458 | struct device_node *db; | ||
459 | |||
460 | base_address = 0; | ||
461 | if (!measure_only) { | ||
462 | for (db = np->parent; db != NULL; db = db->parent) { | ||
463 | if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) { | ||
464 | base_address = db->addrs[0].address; | ||
465 | break; | ||
466 | } | ||
467 | } | ||
468 | } | ||
469 | |||
470 | rp = (struct reg_property32 *) get_property(np, "reg", &l); | ||
471 | if (rp != 0 && l >= sizeof(struct reg_property32)) { | ||
472 | i = 0; | ||
473 | adr = (struct address_range *) (*mem_start); | ||
474 | while ((l -= sizeof(struct reg_property32)) >= 0) { | ||
475 | if (!measure_only) { | ||
476 | adr[i].space = 2; | ||
477 | adr[i].address = rp[i].address + base_address; | ||
478 | adr[i].size = rp[i].size; | ||
479 | } | ||
480 | ++i; | ||
481 | } | ||
482 | np->addrs = adr; | ||
483 | np->n_addrs = i; | ||
484 | (*mem_start) += i * sizeof(struct address_range); | ||
485 | } | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static int __init interpret_macio_props(struct device_node *np, | ||
491 | unsigned long *mem_start, | ||
492 | int naddrc, int nsizec, | ||
493 | int measure_only) | ||
494 | { | ||
495 | struct reg_property32 *rp; | ||
496 | struct address_range *adr; | ||
497 | unsigned long base_address; | ||
498 | int i, l; | ||
499 | struct device_node *db; | ||
500 | |||
501 | base_address = 0; | ||
502 | if (!measure_only) { | ||
503 | for (db = np->parent; db != NULL; db = db->parent) { | ||
504 | if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) { | ||
505 | base_address = db->addrs[0].address; | ||
506 | break; | ||
507 | } | ||
508 | } | ||
509 | } | ||
510 | |||
511 | rp = (struct reg_property32 *) get_property(np, "reg", &l); | ||
512 | if (rp != 0 && l >= sizeof(struct reg_property32)) { | ||
513 | i = 0; | ||
514 | adr = (struct address_range *) (*mem_start); | ||
515 | while ((l -= sizeof(struct reg_property32)) >= 0) { | ||
516 | if (!measure_only) { | ||
517 | adr[i].space = 2; | ||
518 | adr[i].address = rp[i].address + base_address; | ||
519 | adr[i].size = rp[i].size; | ||
520 | } | ||
521 | ++i; | ||
522 | } | ||
523 | np->addrs = adr; | ||
524 | np->n_addrs = i; | ||
525 | (*mem_start) += i * sizeof(struct address_range); | ||
526 | } | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
531 | static int __init interpret_isa_props(struct device_node *np, | ||
532 | unsigned long *mem_start, | ||
533 | int naddrc, int nsizec, | ||
534 | int measure_only) | ||
535 | { | ||
536 | struct isa_reg_property *rp; | ||
537 | struct address_range *adr; | ||
538 | int i, l; | ||
539 | |||
540 | rp = (struct isa_reg_property *) get_property(np, "reg", &l); | ||
541 | if (rp != 0 && l >= sizeof(struct isa_reg_property)) { | ||
542 | i = 0; | ||
543 | adr = (struct address_range *) (*mem_start); | ||
544 | while ((l -= sizeof(struct isa_reg_property)) >= 0) { | ||
545 | if (!measure_only) { | ||
546 | adr[i].space = rp[i].space; | ||
547 | adr[i].address = rp[i].address; | ||
548 | adr[i].size = rp[i].size; | ||
549 | } | ||
550 | ++i; | ||
551 | } | ||
552 | np->addrs = adr; | ||
553 | np->n_addrs = i; | ||
554 | (*mem_start) += i * sizeof(struct address_range); | ||
555 | } | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | static int __init interpret_root_props(struct device_node *np, | ||
561 | unsigned long *mem_start, | ||
562 | int naddrc, int nsizec, | ||
563 | int measure_only) | ||
564 | { | ||
565 | struct address_range *adr; | ||
566 | int i, l; | ||
567 | unsigned int *rp; | ||
568 | int rpsize = (naddrc + nsizec) * sizeof(unsigned int); | ||
569 | |||
570 | rp = (unsigned int *) get_property(np, "linux,usable-memory", &l); | ||
571 | if (rp == NULL) | ||
572 | rp = (unsigned int *) get_property(np, "reg", &l); | ||
573 | |||
574 | if (rp != 0 && l >= rpsize) { | ||
575 | i = 0; | ||
576 | adr = (struct address_range *) (*mem_start); | ||
577 | while ((l -= rpsize) >= 0) { | ||
578 | if (!measure_only) { | ||
579 | adr[i].space = 0; | ||
580 | adr[i].address = rp[naddrc - 1]; | ||
581 | adr[i].size = rp[naddrc + nsizec - 1]; | ||
582 | } | ||
583 | ++i; | ||
584 | rp += naddrc + nsizec; | ||
585 | } | ||
586 | np->addrs = adr; | ||
587 | np->n_addrs = i; | ||
588 | (*mem_start) += i * sizeof(struct address_range); | ||
589 | } | ||
590 | |||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | static int __devinit finish_node(struct device_node *np, | 398 | static int __devinit finish_node(struct device_node *np, |
595 | unsigned long *mem_start, | 399 | unsigned long *mem_start, |
596 | interpret_func *ifunc, | ||
597 | int naddrc, int nsizec, | ||
598 | int measure_only) | 400 | int measure_only) |
599 | { | 401 | { |
600 | struct device_node *child; | 402 | struct device_node *child; |
601 | int *ip, rc = 0; | 403 | int rc = 0; |
602 | |||
603 | /* get the device addresses and interrupts */ | ||
604 | if (ifunc != NULL) | ||
605 | rc = ifunc(np, mem_start, naddrc, nsizec, measure_only); | ||
606 | if (rc) | ||
607 | goto out; | ||
608 | 404 | ||
609 | rc = finish_node_interrupts(np, mem_start, measure_only); | 405 | rc = finish_node_interrupts(np, mem_start, measure_only); |
610 | if (rc) | 406 | if (rc) |
611 | goto out; | 407 | goto out; |
612 | 408 | ||
613 | /* Look for #address-cells and #size-cells properties. */ | ||
614 | ip = (int *) get_property(np, "#address-cells", NULL); | ||
615 | if (ip != NULL) | ||
616 | naddrc = *ip; | ||
617 | ip = (int *) get_property(np, "#size-cells", NULL); | ||
618 | if (ip != NULL) | ||
619 | nsizec = *ip; | ||
620 | |||
621 | if (!strcmp(np->name, "device-tree") || np->parent == NULL) | ||
622 | ifunc = interpret_root_props; | ||
623 | else if (np->type == 0) | ||
624 | ifunc = NULL; | ||
625 | else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci")) | ||
626 | ifunc = interpret_pci_props; | ||
627 | else if (!strcmp(np->type, "dbdma")) | ||
628 | ifunc = interpret_dbdma_props; | ||
629 | else if (!strcmp(np->type, "mac-io") || ifunc == interpret_macio_props) | ||
630 | ifunc = interpret_macio_props; | ||
631 | else if (!strcmp(np->type, "isa")) | ||
632 | ifunc = interpret_isa_props; | ||
633 | else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3")) | ||
634 | ifunc = interpret_root_props; | ||
635 | else if (!((ifunc == interpret_dbdma_props | ||
636 | || ifunc == interpret_macio_props) | ||
637 | && (!strcmp(np->type, "escc") | ||
638 | || !strcmp(np->type, "media-bay")))) | ||
639 | ifunc = NULL; | ||
640 | |||
641 | for (child = np->child; child != NULL; child = child->sibling) { | 409 | for (child = np->child; child != NULL; child = child->sibling) { |
642 | rc = finish_node(child, mem_start, ifunc, | 410 | rc = finish_node(child, mem_start, measure_only); |
643 | naddrc, nsizec, measure_only); | ||
644 | if (rc) | 411 | if (rc) |
645 | goto out; | 412 | goto out; |
646 | } | 413 | } |
@@ -702,10 +469,10 @@ void __init finish_device_tree(void) | |||
702 | * reason and then remove those additional 16 bytes | 469 | * reason and then remove those additional 16 bytes |
703 | */ | 470 | */ |
704 | size = 16; | 471 | size = 16; |
705 | finish_node(allnodes, &size, NULL, 0, 0, 1); | 472 | finish_node(allnodes, &size, 1); |
706 | size -= 16; | 473 | size -= 16; |
707 | end = start = (unsigned long) __va(lmb_alloc(size, 128)); | 474 | end = start = (unsigned long) __va(lmb_alloc(size, 128)); |
708 | finish_node(allnodes, &end, NULL, 0, 0, 0); | 475 | finish_node(allnodes, &end, 0); |
709 | BUG_ON(end != start + size); | 476 | BUG_ON(end != start + size); |
710 | 477 | ||
711 | DBG(" <- finish_device_tree\n"); | 478 | DBG(" <- finish_device_tree\n"); |
@@ -1822,7 +1589,6 @@ static void of_node_release(struct kref *kref) | |||
1822 | prop = next; | 1589 | prop = next; |
1823 | } | 1590 | } |
1824 | kfree(node->intrs); | 1591 | kfree(node->intrs); |
1825 | kfree(node->addrs); | ||
1826 | kfree(node->full_name); | 1592 | kfree(node->full_name); |
1827 | kfree(node->data); | 1593 | kfree(node->data); |
1828 | kfree(node); | 1594 | kfree(node); |
@@ -1904,9 +1670,7 @@ void of_detach_node(const struct device_node *np) | |||
1904 | * This should probably be split up into smaller chunks. | 1670 | * This should probably be split up into smaller chunks. |
1905 | */ | 1671 | */ |
1906 | 1672 | ||
1907 | static int of_finish_dynamic_node(struct device_node *node, | 1673 | static int of_finish_dynamic_node(struct device_node *node) |
1908 | unsigned long *unused1, int unused2, | ||
1909 | int unused3, int unused4) | ||
1910 | { | 1674 | { |
1911 | struct device_node *parent = of_get_parent(node); | 1675 | struct device_node *parent = of_get_parent(node); |
1912 | int err = 0; | 1676 | int err = 0; |
@@ -1927,7 +1691,8 @@ static int of_finish_dynamic_node(struct device_node *node, | |||
1927 | return -ENODEV; | 1691 | return -ENODEV; |
1928 | 1692 | ||
1929 | /* fix up new node's linux_phandle field */ | 1693 | /* fix up new node's linux_phandle field */ |
1930 | if ((ibm_phandle = (unsigned int *)get_property(node, "ibm,phandle", NULL))) | 1694 | if ((ibm_phandle = (unsigned int *)get_property(node, |
1695 | "ibm,phandle", NULL))) | ||
1931 | node->linux_phandle = *ibm_phandle; | 1696 | node->linux_phandle = *ibm_phandle; |
1932 | 1697 | ||
1933 | out: | 1698 | out: |
@@ -1942,7 +1707,9 @@ static int prom_reconfig_notifier(struct notifier_block *nb, | |||
1942 | 1707 | ||
1943 | switch (action) { | 1708 | switch (action) { |
1944 | case PSERIES_RECONFIG_ADD: | 1709 | case PSERIES_RECONFIG_ADD: |
1945 | err = finish_node(node, NULL, of_finish_dynamic_node, 0, 0, 0); | 1710 | err = of_finish_dynamic_node(node); |
1711 | if (!err) | ||
1712 | finish_node(node, NULL, 0); | ||
1946 | if (err < 0) { | 1713 | if (err < 0) { |
1947 | printk(KERN_ERR "finish_node returned %d\n", err); | 1714 | printk(KERN_ERR "finish_node returned %d\n", err); |
1948 | err = NOTIFY_BAD; | 1715 | err = NOTIFY_BAD; |
@@ -2016,175 +1783,4 @@ int prom_add_property(struct device_node* np, struct property* prop) | |||
2016 | return 0; | 1783 | return 0; |
2017 | } | 1784 | } |
2018 | 1785 | ||
2019 | /* I quickly hacked that one, check against spec ! */ | ||
2020 | static inline unsigned long | ||
2021 | bus_space_to_resource_flags(unsigned int bus_space) | ||
2022 | { | ||
2023 | u8 space = (bus_space >> 24) & 0xf; | ||
2024 | if (space == 0) | ||
2025 | space = 0x02; | ||
2026 | if (space == 0x02) | ||
2027 | return IORESOURCE_MEM; | ||
2028 | else if (space == 0x01) | ||
2029 | return IORESOURCE_IO; | ||
2030 | else { | ||
2031 | printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %x\n", | ||
2032 | bus_space); | ||
2033 | return 0; | ||
2034 | } | ||
2035 | } | ||
2036 | |||
2037 | #ifdef CONFIG_PCI | ||
2038 | static struct resource *find_parent_pci_resource(struct pci_dev* pdev, | ||
2039 | struct address_range *range) | ||
2040 | { | ||
2041 | unsigned long mask; | ||
2042 | int i; | ||
2043 | |||
2044 | /* Check this one */ | ||
2045 | mask = bus_space_to_resource_flags(range->space); | ||
2046 | for (i=0; i<DEVICE_COUNT_RESOURCE; i++) { | ||
2047 | if ((pdev->resource[i].flags & mask) == mask && | ||
2048 | pdev->resource[i].start <= range->address && | ||
2049 | pdev->resource[i].end > range->address) { | ||
2050 | if ((range->address + range->size - 1) > pdev->resource[i].end) { | ||
2051 | /* Add better message */ | ||
2052 | printk(KERN_WARNING "PCI/OF resource overlap !\n"); | ||
2053 | return NULL; | ||
2054 | } | ||
2055 | break; | ||
2056 | } | ||
2057 | } | ||
2058 | if (i == DEVICE_COUNT_RESOURCE) | ||
2059 | return NULL; | ||
2060 | return &pdev->resource[i]; | ||
2061 | } | ||
2062 | |||
2063 | /* | ||
2064 | * Request an OF device resource. Currently handles child of PCI devices, | ||
2065 | * or other nodes attached to the root node. Ultimately, put some | ||
2066 | * link to resources in the OF node. | ||
2067 | */ | ||
2068 | struct resource *request_OF_resource(struct device_node* node, int index, | ||
2069 | const char* name_postfix) | ||
2070 | { | ||
2071 | struct pci_dev* pcidev; | ||
2072 | u8 pci_bus, pci_devfn; | ||
2073 | unsigned long iomask; | ||
2074 | struct device_node* nd; | ||
2075 | struct resource* parent; | ||
2076 | struct resource *res = NULL; | ||
2077 | int nlen, plen; | ||
2078 | |||
2079 | if (index >= node->n_addrs) | ||
2080 | goto fail; | ||
2081 | |||
2082 | /* Sanity check on bus space */ | ||
2083 | iomask = bus_space_to_resource_flags(node->addrs[index].space); | ||
2084 | if (iomask & IORESOURCE_MEM) | ||
2085 | parent = &iomem_resource; | ||
2086 | else if (iomask & IORESOURCE_IO) | ||
2087 | parent = &ioport_resource; | ||
2088 | else | ||
2089 | goto fail; | ||
2090 | |||
2091 | /* Find a PCI parent if any */ | ||
2092 | nd = node; | ||
2093 | pcidev = NULL; | ||
2094 | while (nd) { | ||
2095 | if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn)) | ||
2096 | pcidev = pci_find_slot(pci_bus, pci_devfn); | ||
2097 | if (pcidev) break; | ||
2098 | nd = nd->parent; | ||
2099 | } | ||
2100 | if (pcidev) | ||
2101 | parent = find_parent_pci_resource(pcidev, &node->addrs[index]); | ||
2102 | if (!parent) { | ||
2103 | printk(KERN_WARNING "request_OF_resource(%s), parent not found\n", | ||
2104 | node->name); | ||
2105 | goto fail; | ||
2106 | } | ||
2107 | |||
2108 | res = __request_region(parent, node->addrs[index].address, | ||
2109 | node->addrs[index].size, NULL); | ||
2110 | if (!res) | ||
2111 | goto fail; | ||
2112 | nlen = strlen(node->name); | ||
2113 | plen = name_postfix ? strlen(name_postfix) : 0; | ||
2114 | res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL); | ||
2115 | if (res->name) { | ||
2116 | strcpy((char *)res->name, node->name); | ||
2117 | if (plen) | ||
2118 | strcpy((char *)res->name+nlen, name_postfix); | ||
2119 | } | ||
2120 | return res; | ||
2121 | fail: | ||
2122 | return NULL; | ||
2123 | } | ||
2124 | EXPORT_SYMBOL(request_OF_resource); | ||
2125 | |||
2126 | int release_OF_resource(struct device_node *node, int index) | ||
2127 | { | ||
2128 | struct pci_dev* pcidev; | ||
2129 | u8 pci_bus, pci_devfn; | ||
2130 | unsigned long iomask, start, end; | ||
2131 | struct device_node* nd; | ||
2132 | struct resource* parent; | ||
2133 | struct resource *res = NULL; | ||
2134 | |||
2135 | if (index >= node->n_addrs) | ||
2136 | return -EINVAL; | ||
2137 | |||
2138 | /* Sanity check on bus space */ | ||
2139 | iomask = bus_space_to_resource_flags(node->addrs[index].space); | ||
2140 | if (iomask & IORESOURCE_MEM) | ||
2141 | parent = &iomem_resource; | ||
2142 | else if (iomask & IORESOURCE_IO) | ||
2143 | parent = &ioport_resource; | ||
2144 | else | ||
2145 | return -EINVAL; | ||
2146 | |||
2147 | /* Find a PCI parent if any */ | ||
2148 | nd = node; | ||
2149 | pcidev = NULL; | ||
2150 | while(nd) { | ||
2151 | if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn)) | ||
2152 | pcidev = pci_find_slot(pci_bus, pci_devfn); | ||
2153 | if (pcidev) break; | ||
2154 | nd = nd->parent; | ||
2155 | } | ||
2156 | if (pcidev) | ||
2157 | parent = find_parent_pci_resource(pcidev, &node->addrs[index]); | ||
2158 | if (!parent) { | ||
2159 | printk(KERN_WARNING "release_OF_resource(%s), parent not found\n", | ||
2160 | node->name); | ||
2161 | return -ENODEV; | ||
2162 | } | ||
2163 | 1786 | ||
2164 | /* Find us in the parent and its childs */ | ||
2165 | res = parent->child; | ||
2166 | start = node->addrs[index].address; | ||
2167 | end = start + node->addrs[index].size - 1; | ||
2168 | while (res) { | ||
2169 | if (res->start == start && res->end == end && | ||
2170 | (res->flags & IORESOURCE_BUSY)) | ||
2171 | break; | ||
2172 | if (res->start <= start && res->end >= end) | ||
2173 | res = res->child; | ||
2174 | else | ||
2175 | res = res->sibling; | ||
2176 | } | ||
2177 | if (!res) | ||
2178 | return -ENODEV; | ||
2179 | |||
2180 | if (res->name) { | ||
2181 | kfree(res->name); | ||
2182 | res->name = NULL; | ||
2183 | } | ||
2184 | release_resource(res); | ||
2185 | kfree(res); | ||
2186 | |||
2187 | return 0; | ||
2188 | } | ||
2189 | EXPORT_SYMBOL(release_OF_resource); | ||
2190 | #endif /* CONFIG_PCI */ | ||
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 6007d51d119b..e381f2fc121c 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -558,7 +558,8 @@ unsigned long prom_memparse(const char *ptr, const char **retptr) | |||
558 | static void __init early_cmdline_parse(void) | 558 | static void __init early_cmdline_parse(void) |
559 | { | 559 | { |
560 | struct prom_t *_prom = &RELOC(prom); | 560 | struct prom_t *_prom = &RELOC(prom); |
561 | char *opt, *p; | 561 | const char *opt; |
562 | char *p; | ||
562 | int l = 0; | 563 | int l = 0; |
563 | 564 | ||
564 | RELOC(prom_cmd_line[0]) = 0; | 565 | RELOC(prom_cmd_line[0]) = 0; |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 60dec2401c26..45b8109951fe 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
@@ -188,39 +188,19 @@ int is_python(struct device_node *dev) | |||
188 | return 0; | 188 | return 0; |
189 | } | 189 | } |
190 | 190 | ||
191 | static int get_phb_reg_prop(struct device_node *dev, | 191 | static void python_countermeasures(struct device_node *dev) |
192 | unsigned int addr_size_words, | ||
193 | struct reg_property64 *reg) | ||
194 | { | 192 | { |
195 | unsigned int *ui_ptr = NULL, len; | 193 | struct resource registers; |
196 | |||
197 | /* Found a PHB, now figure out where his registers are mapped. */ | ||
198 | ui_ptr = (unsigned int *)get_property(dev, "reg", &len); | ||
199 | if (ui_ptr == NULL) | ||
200 | return 1; | ||
201 | |||
202 | if (addr_size_words == 1) { | ||
203 | reg->address = ((struct reg_property32 *)ui_ptr)->address; | ||
204 | reg->size = ((struct reg_property32 *)ui_ptr)->size; | ||
205 | } else { | ||
206 | *reg = *((struct reg_property64 *)ui_ptr); | ||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static void python_countermeasures(struct device_node *dev, | ||
213 | unsigned int addr_size_words) | ||
214 | { | ||
215 | struct reg_property64 reg_struct; | ||
216 | void __iomem *chip_regs; | 194 | void __iomem *chip_regs; |
217 | volatile u32 val; | 195 | volatile u32 val; |
218 | 196 | ||
219 | if (get_phb_reg_prop(dev, addr_size_words, ®_struct)) | 197 | if (of_address_to_resource(dev, 0, ®isters)) { |
198 | printk(KERN_ERR "Can't get address for Python workarounds !\n"); | ||
220 | return; | 199 | return; |
200 | } | ||
221 | 201 | ||
222 | /* Python's register file is 1 MB in size. */ | 202 | /* Python's register file is 1 MB in size. */ |
223 | chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000); | 203 | chip_regs = ioremap(registers.start & ~(0xfffffUL), 0x100000); |
224 | 204 | ||
225 | /* | 205 | /* |
226 | * Firmware doesn't always clear this bit which is critical | 206 | * Firmware doesn't always clear this bit which is critical |
@@ -301,11 +281,10 @@ static int phb_set_bus_ranges(struct device_node *dev, | |||
301 | } | 281 | } |
302 | 282 | ||
303 | static int __devinit setup_phb(struct device_node *dev, | 283 | static int __devinit setup_phb(struct device_node *dev, |
304 | struct pci_controller *phb, | 284 | struct pci_controller *phb) |
305 | unsigned int addr_size_words) | ||
306 | { | 285 | { |
307 | if (is_python(dev)) | 286 | if (is_python(dev)) |
308 | python_countermeasures(dev, addr_size_words); | 287 | python_countermeasures(dev); |
309 | 288 | ||
310 | if (phb_set_bus_ranges(dev, phb)) | 289 | if (phb_set_bus_ranges(dev, phb)) |
311 | return 1; | 290 | return 1; |
@@ -320,8 +299,8 @@ unsigned long __init find_and_init_phbs(void) | |||
320 | { | 299 | { |
321 | struct device_node *node; | 300 | struct device_node *node; |
322 | struct pci_controller *phb; | 301 | struct pci_controller *phb; |
323 | unsigned int root_size_cells = 0; | ||
324 | unsigned int index; | 302 | unsigned int index; |
303 | unsigned int root_size_cells = 0; | ||
325 | unsigned int *opprop = NULL; | 304 | unsigned int *opprop = NULL; |
326 | struct device_node *root = of_find_node_by_path("/"); | 305 | struct device_node *root = of_find_node_by_path("/"); |
327 | 306 | ||
@@ -343,10 +322,11 @@ unsigned long __init find_and_init_phbs(void) | |||
343 | phb = pcibios_alloc_controller(node); | 322 | phb = pcibios_alloc_controller(node); |
344 | if (!phb) | 323 | if (!phb) |
345 | continue; | 324 | continue; |
346 | setup_phb(node, phb, root_size_cells); | 325 | setup_phb(node, phb); |
347 | pci_process_bridge_OF_ranges(phb, node, 0); | 326 | pci_process_bridge_OF_ranges(phb, node, 0); |
348 | pci_setup_phb_io(phb, index == 0); | 327 | pci_setup_phb_io(phb, index == 0); |
349 | #ifdef CONFIG_PPC_PSERIES | 328 | #ifdef CONFIG_PPC_PSERIES |
329 | /* XXX This code need serious fixing ... --BenH */ | ||
350 | if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) { | 330 | if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) { |
351 | int addr = root_size_cells * (index + 2) - 1; | 331 | int addr = root_size_cells * (index + 2) - 1; |
352 | mpic_assign_isu(pSeries_mpic, index, opprop[addr]); | 332 | mpic_assign_isu(pSeries_mpic, index, opprop[addr]); |
@@ -381,22 +361,17 @@ unsigned long __init find_and_init_phbs(void) | |||
381 | 361 | ||
382 | struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | 362 | struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) |
383 | { | 363 | { |
384 | struct device_node *root = of_find_node_by_path("/"); | ||
385 | unsigned int root_size_cells = 0; | ||
386 | struct pci_controller *phb; | 364 | struct pci_controller *phb; |
387 | int primary; | 365 | int primary; |
388 | 366 | ||
389 | root_size_cells = prom_n_size_cells(root); | ||
390 | |||
391 | primary = list_empty(&hose_list); | 367 | primary = list_empty(&hose_list); |
392 | phb = pcibios_alloc_controller(dn); | 368 | phb = pcibios_alloc_controller(dn); |
393 | if (!phb) | 369 | if (!phb) |
394 | return NULL; | 370 | return NULL; |
395 | setup_phb(dn, phb, root_size_cells); | 371 | setup_phb(dn, phb); |
396 | pci_process_bridge_OF_ranges(phb, dn, primary); | 372 | pci_process_bridge_OF_ranges(phb, dn, primary); |
397 | 373 | ||
398 | pci_setup_phb_io_dynamic(phb, primary); | 374 | pci_setup_phb_io_dynamic(phb, primary); |
399 | of_node_put(root); | ||
400 | 375 | ||
401 | pci_devs_phb_init_dynamic(phb); | 376 | pci_devs_phb_init_dynamic(phb); |
402 | scan_phb(phb); | 377 | scan_phb(phb); |