diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-04 13:02:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-04 13:02:38 -0400 |
commit | d27050641e9bc056446deb0814e7ba1aa7911f5a (patch) | |
tree | 160f46d9a6df3d7234c71a9fbaa31ebcf89c04d0 /drivers/of | |
parent | b77279bc2e81545b20824da701b349272a78e4e7 (diff) | |
parent | 43cb43678705e39b175b325f17938295996aefc7 (diff) |
Merge tag 'devicetree-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux into next
Pull DeviceTree updates from Rob Herring:
- Another round of clean-up of FDT related code in architecture code.
This removes knowledge of internal FDT details from most
architectures except powerpc.
- Conversion of kernel's custom FDT parsing code to use libfdt.
- DT based initialization for generic serial earlycon. The
introduction of generic serial earlycon support went in through the
tty tree.
- Improve the platform device naming for DT probed devices to ensure
unique naming and use parent names instead of a global index.
- Fix a race condition in of_update_property.
- Unify the various linker section OF match tables and fix several
function prototype errors.
- Update platform_get_irq_byname to work in deferred probe cases.
- 2 binding doc updates
* tag 'devicetree-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (58 commits)
of: handle NULL node in next_child iterators
of/irq: provide more wrappers for !CONFIG_OF
devicetree: bindings: Document micrel vendor prefix
dt: bindings: dwc2: fix required value for the phy-names property
of_pci_irq: kill useless variable in of_irq_parse_pci()
of/irq: do irq resolution in platform_get_irq_byname()
of: Add a testcase for of_find_node_by_path()
of: Make of_find_node_by_path() handle /aliases
of: Create unlocked version of for_each_child_of_node()
lib: add glibc style strchrnul() variant
of: Handle memory@0 node on PPC32 only
pci/of: Remove dead code
of: fix race between search and remove in of_update_property()
of: Use NULL for pointers
of: Stop naming platform_device using dcr address
of: Ensure unique names without sacrificing determinism
tty/serial: pl011: add DT based earlycon support
of/fdt: add FDT serial scanning for earlycon
of/fdt: add FDT address translation support
serial: earlycon: add DT support
...
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/Kconfig | 1 | ||||
-rw-r--r-- | drivers/of/Makefile | 4 | ||||
-rw-r--r-- | drivers/of/address.c | 22 | ||||
-rw-r--r-- | drivers/of/base.c | 119 | ||||
-rw-r--r-- | drivers/of/fdt.c | 458 | ||||
-rw-r--r-- | drivers/of/fdt_address.c | 241 | ||||
-rw-r--r-- | drivers/of/irq.c | 22 | ||||
-rw-r--r-- | drivers/of/of_pci_irq.c | 8 | ||||
-rw-r--r-- | drivers/of/of_reserved_mem.c | 6 | ||||
-rw-r--r-- | drivers/of/platform.c | 76 | ||||
-rw-r--r-- | drivers/of/selftest.c | 80 | ||||
-rw-r--r-- | drivers/of/testcase-data/testcases.dtsi | 1 | ||||
-rw-r--r-- | drivers/of/testcase-data/tests-phandle.dtsi | 6 | ||||
-rw-r--r-- | drivers/of/testcase-data/tests-platform.dtsi | 35 |
14 files changed, 698 insertions, 381 deletions
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 889005fa4d04..2dcb0541012d 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig | |||
@@ -20,6 +20,7 @@ config OF_SELFTEST | |||
20 | config OF_FLATTREE | 20 | config OF_FLATTREE |
21 | bool | 21 | bool |
22 | select DTC | 22 | select DTC |
23 | select LIBFDT | ||
23 | 24 | ||
24 | config OF_EARLY_FLATTREE | 25 | config OF_EARLY_FLATTREE |
25 | bool | 26 | bool |
diff --git a/drivers/of/Makefile b/drivers/of/Makefile index ed9660adad77..099b1fb00af4 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | obj-y = base.o device.o platform.o | 1 | obj-y = base.o device.o platform.o |
2 | obj-$(CONFIG_OF_FLATTREE) += fdt.o | 2 | obj-$(CONFIG_OF_FLATTREE) += fdt.o |
3 | obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o | ||
3 | obj-$(CONFIG_OF_PROMTREE) += pdt.o | 4 | obj-$(CONFIG_OF_PROMTREE) += pdt.o |
4 | obj-$(CONFIG_OF_ADDRESS) += address.o | 5 | obj-$(CONFIG_OF_ADDRESS) += address.o |
5 | obj-$(CONFIG_OF_IRQ) += irq.o | 6 | obj-$(CONFIG_OF_IRQ) += irq.o |
@@ -10,3 +11,6 @@ obj-$(CONFIG_OF_PCI) += of_pci.o | |||
10 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o | 11 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o |
11 | obj-$(CONFIG_OF_MTD) += of_mtd.o | 12 | obj-$(CONFIG_OF_MTD) += of_mtd.o |
12 | obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o | 13 | obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o |
14 | |||
15 | CFLAGS_fdt.o = -I$(src)/../../scripts/dtc/libfdt | ||
16 | CFLAGS_fdt_address.o = -I$(src)/../../scripts/dtc/libfdt | ||
diff --git a/drivers/of/address.c b/drivers/of/address.c index cb4242a69cd5..95351b2a112c 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c | |||
@@ -498,8 +498,7 @@ static u64 __of_translate_address(struct device_node *dev, | |||
498 | /* Count address cells & copy address locally */ | 498 | /* Count address cells & copy address locally */ |
499 | bus->count_cells(dev, &na, &ns); | 499 | bus->count_cells(dev, &na, &ns); |
500 | if (!OF_CHECK_COUNTS(na, ns)) { | 500 | if (!OF_CHECK_COUNTS(na, ns)) { |
501 | printk(KERN_ERR "prom_parse: Bad cell count for %s\n", | 501 | pr_debug("OF: Bad cell count for %s\n", of_node_full_name(dev)); |
502 | of_node_full_name(dev)); | ||
503 | goto bail; | 502 | goto bail; |
504 | } | 503 | } |
505 | memcpy(addr, in_addr, na * 4); | 504 | memcpy(addr, in_addr, na * 4); |
@@ -564,25 +563,6 @@ u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) | |||
564 | } | 563 | } |
565 | EXPORT_SYMBOL(of_translate_dma_address); | 564 | EXPORT_SYMBOL(of_translate_dma_address); |
566 | 565 | ||
567 | bool of_can_translate_address(struct device_node *dev) | ||
568 | { | ||
569 | struct device_node *parent; | ||
570 | struct of_bus *bus; | ||
571 | int na, ns; | ||
572 | |||
573 | parent = of_get_parent(dev); | ||
574 | if (parent == NULL) | ||
575 | return false; | ||
576 | |||
577 | bus = of_match_bus(parent); | ||
578 | bus->count_cells(dev, &na, &ns); | ||
579 | |||
580 | of_node_put(parent); | ||
581 | |||
582 | return OF_CHECK_COUNTS(na, ns); | ||
583 | } | ||
584 | EXPORT_SYMBOL(of_can_translate_address); | ||
585 | |||
586 | const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, | 566 | const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, |
587 | unsigned int *flags) | 567 | unsigned int *flags) |
588 | { | 568 | { |
diff --git a/drivers/of/base.c b/drivers/of/base.c index aab9728271fd..8368d96ae7b4 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -695,6 +695,25 @@ struct device_node *of_get_next_parent(struct device_node *node) | |||
695 | } | 695 | } |
696 | EXPORT_SYMBOL(of_get_next_parent); | 696 | EXPORT_SYMBOL(of_get_next_parent); |
697 | 697 | ||
698 | static struct device_node *__of_get_next_child(const struct device_node *node, | ||
699 | struct device_node *prev) | ||
700 | { | ||
701 | struct device_node *next; | ||
702 | |||
703 | if (!node) | ||
704 | return NULL; | ||
705 | |||
706 | next = prev ? prev->sibling : node->child; | ||
707 | for (; next; next = next->sibling) | ||
708 | if (of_node_get(next)) | ||
709 | break; | ||
710 | of_node_put(prev); | ||
711 | return next; | ||
712 | } | ||
713 | #define __for_each_child_of_node(parent, child) \ | ||
714 | for (child = __of_get_next_child(parent, NULL); child != NULL; \ | ||
715 | child = __of_get_next_child(parent, child)) | ||
716 | |||
698 | /** | 717 | /** |
699 | * of_get_next_child - Iterate a node childs | 718 | * of_get_next_child - Iterate a node childs |
700 | * @node: parent node | 719 | * @node: parent node |
@@ -710,11 +729,7 @@ struct device_node *of_get_next_child(const struct device_node *node, | |||
710 | unsigned long flags; | 729 | unsigned long flags; |
711 | 730 | ||
712 | raw_spin_lock_irqsave(&devtree_lock, flags); | 731 | raw_spin_lock_irqsave(&devtree_lock, flags); |
713 | next = prev ? prev->sibling : node->child; | 732 | next = __of_get_next_child(node, prev); |
714 | for (; next; next = next->sibling) | ||
715 | if (of_node_get(next)) | ||
716 | break; | ||
717 | of_node_put(prev); | ||
718 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 733 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
719 | return next; | 734 | return next; |
720 | } | 735 | } |
@@ -734,6 +749,9 @@ struct device_node *of_get_next_available_child(const struct device_node *node, | |||
734 | struct device_node *next; | 749 | struct device_node *next; |
735 | unsigned long flags; | 750 | unsigned long flags; |
736 | 751 | ||
752 | if (!node) | ||
753 | return NULL; | ||
754 | |||
737 | raw_spin_lock_irqsave(&devtree_lock, flags); | 755 | raw_spin_lock_irqsave(&devtree_lock, flags); |
738 | next = prev ? prev->sibling : node->child; | 756 | next = prev ? prev->sibling : node->child; |
739 | for (; next; next = next->sibling) { | 757 | for (; next; next = next->sibling) { |
@@ -771,23 +789,78 @@ struct device_node *of_get_child_by_name(const struct device_node *node, | |||
771 | } | 789 | } |
772 | EXPORT_SYMBOL(of_get_child_by_name); | 790 | EXPORT_SYMBOL(of_get_child_by_name); |
773 | 791 | ||
792 | static struct device_node *__of_find_node_by_path(struct device_node *parent, | ||
793 | const char *path) | ||
794 | { | ||
795 | struct device_node *child; | ||
796 | int len = strchrnul(path, '/') - path; | ||
797 | |||
798 | if (!len) | ||
799 | return NULL; | ||
800 | |||
801 | __for_each_child_of_node(parent, child) { | ||
802 | const char *name = strrchr(child->full_name, '/'); | ||
803 | if (WARN(!name, "malformed device_node %s\n", child->full_name)) | ||
804 | continue; | ||
805 | name++; | ||
806 | if (strncmp(path, name, len) == 0 && (strlen(name) == len)) | ||
807 | return child; | ||
808 | } | ||
809 | return NULL; | ||
810 | } | ||
811 | |||
774 | /** | 812 | /** |
775 | * of_find_node_by_path - Find a node matching a full OF path | 813 | * of_find_node_by_path - Find a node matching a full OF path |
776 | * @path: The full path to match | 814 | * @path: Either the full path to match, or if the path does not |
815 | * start with '/', the name of a property of the /aliases | ||
816 | * node (an alias). In the case of an alias, the node | ||
817 | * matching the alias' value will be returned. | ||
818 | * | ||
819 | * Valid paths: | ||
820 | * /foo/bar Full path | ||
821 | * foo Valid alias | ||
822 | * foo/bar Valid alias + relative path | ||
777 | * | 823 | * |
778 | * Returns a node pointer with refcount incremented, use | 824 | * Returns a node pointer with refcount incremented, use |
779 | * of_node_put() on it when done. | 825 | * of_node_put() on it when done. |
780 | */ | 826 | */ |
781 | struct device_node *of_find_node_by_path(const char *path) | 827 | struct device_node *of_find_node_by_path(const char *path) |
782 | { | 828 | { |
783 | struct device_node *np = of_allnodes; | 829 | struct device_node *np = NULL; |
830 | struct property *pp; | ||
784 | unsigned long flags; | 831 | unsigned long flags; |
785 | 832 | ||
833 | if (strcmp(path, "/") == 0) | ||
834 | return of_node_get(of_allnodes); | ||
835 | |||
836 | /* The path could begin with an alias */ | ||
837 | if (*path != '/') { | ||
838 | char *p = strchrnul(path, '/'); | ||
839 | int len = p - path; | ||
840 | |||
841 | /* of_aliases must not be NULL */ | ||
842 | if (!of_aliases) | ||
843 | return NULL; | ||
844 | |||
845 | for_each_property_of_node(of_aliases, pp) { | ||
846 | if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) { | ||
847 | np = of_find_node_by_path(pp->value); | ||
848 | break; | ||
849 | } | ||
850 | } | ||
851 | if (!np) | ||
852 | return NULL; | ||
853 | path = p; | ||
854 | } | ||
855 | |||
856 | /* Step down the tree matching path components */ | ||
786 | raw_spin_lock_irqsave(&devtree_lock, flags); | 857 | raw_spin_lock_irqsave(&devtree_lock, flags); |
787 | for (; np; np = np->allnext) { | 858 | if (!np) |
788 | if (np->full_name && (of_node_cmp(np->full_name, path) == 0) | 859 | np = of_node_get(of_allnodes); |
789 | && of_node_get(np)) | 860 | while (np && *path == '/') { |
790 | break; | 861 | path++; /* Increment past '/' delimiter */ |
862 | np = __of_find_node_by_path(np, path); | ||
863 | path = strchrnul(path, '/'); | ||
791 | } | 864 | } |
792 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 865 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
793 | return np; | 866 | return np; |
@@ -1800,7 +1873,7 @@ int of_update_property(struct device_node *np, struct property *newprop) | |||
1800 | { | 1873 | { |
1801 | struct property **next, *oldprop; | 1874 | struct property **next, *oldprop; |
1802 | unsigned long flags; | 1875 | unsigned long flags; |
1803 | int rc, found = 0; | 1876 | int rc; |
1804 | 1877 | ||
1805 | rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); | 1878 | rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); |
1806 | if (rc) | 1879 | if (rc) |
@@ -1809,34 +1882,34 @@ int of_update_property(struct device_node *np, struct property *newprop) | |||
1809 | if (!newprop->name) | 1882 | if (!newprop->name) |
1810 | return -EINVAL; | 1883 | return -EINVAL; |
1811 | 1884 | ||
1812 | oldprop = of_find_property(np, newprop->name, NULL); | ||
1813 | if (!oldprop) | ||
1814 | return of_add_property(np, newprop); | ||
1815 | |||
1816 | raw_spin_lock_irqsave(&devtree_lock, flags); | 1885 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1817 | next = &np->properties; | 1886 | next = &np->properties; |
1818 | while (*next) { | 1887 | oldprop = __of_find_property(np, newprop->name, NULL); |
1888 | if (!oldprop) { | ||
1889 | /* add the new node */ | ||
1890 | rc = __of_add_property(np, newprop); | ||
1891 | } else while (*next) { | ||
1892 | /* replace the node */ | ||
1819 | if (*next == oldprop) { | 1893 | if (*next == oldprop) { |
1820 | /* found the node */ | ||
1821 | newprop->next = oldprop->next; | 1894 | newprop->next = oldprop->next; |
1822 | *next = newprop; | 1895 | *next = newprop; |
1823 | oldprop->next = np->deadprops; | 1896 | oldprop->next = np->deadprops; |
1824 | np->deadprops = oldprop; | 1897 | np->deadprops = oldprop; |
1825 | found = 1; | ||
1826 | break; | 1898 | break; |
1827 | } | 1899 | } |
1828 | next = &(*next)->next; | 1900 | next = &(*next)->next; |
1829 | } | 1901 | } |
1830 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 1902 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1831 | if (!found) | 1903 | if (rc) |
1832 | return -ENODEV; | 1904 | return rc; |
1833 | 1905 | ||
1834 | /* At early boot, bail out and defer setup to of_init() */ | 1906 | /* At early boot, bail out and defer setup to of_init() */ |
1835 | if (!of_kset) | 1907 | if (!of_kset) |
1836 | return found ? 0 : -ENODEV; | 1908 | return 0; |
1837 | 1909 | ||
1838 | /* Update the sysfs attribute */ | 1910 | /* Update the sysfs attribute */ |
1839 | sysfs_remove_bin_file(&np->kobj, &oldprop->attr); | 1911 | if (oldprop) |
1912 | sysfs_remove_bin_file(&np->kobj, &oldprop->attr); | ||
1840 | __of_add_property_sysfs(np, newprop); | 1913 | __of_add_property_sysfs(np, newprop); |
1841 | 1914 | ||
1842 | return 0; | 1915 | return 0; |
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 7a2ef7bb8022..c4cddf0cd96d 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/initrd.h> | 13 | #include <linux/initrd.h> |
14 | #include <linux/memblock.h> | 14 | #include <linux/memblock.h> |
15 | #include <linux/module.h> | ||
16 | #include <linux/of.h> | 15 | #include <linux/of.h> |
17 | #include <linux/of_fdt.h> | 16 | #include <linux/of_fdt.h> |
18 | #include <linux/of_reserved_mem.h> | 17 | #include <linux/of_reserved_mem.h> |
@@ -20,62 +19,13 @@ | |||
20 | #include <linux/string.h> | 19 | #include <linux/string.h> |
21 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
22 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/libfdt.h> | ||
23 | #include <linux/debugfs.h> | ||
24 | #include <linux/serial_core.h> | ||
23 | 25 | ||
24 | #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ | 26 | #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ |
25 | #ifdef CONFIG_PPC | ||
26 | #include <asm/machdep.h> | ||
27 | #endif /* CONFIG_PPC */ | ||
28 | |||
29 | #include <asm/page.h> | 27 | #include <asm/page.h> |
30 | 28 | ||
31 | char *of_fdt_get_string(struct boot_param_header *blob, u32 offset) | ||
32 | { | ||
33 | return ((char *)blob) + | ||
34 | be32_to_cpu(blob->off_dt_strings) + offset; | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * of_fdt_get_property - Given a node in the given flat blob, return | ||
39 | * the property ptr | ||
40 | */ | ||
41 | void *of_fdt_get_property(struct boot_param_header *blob, | ||
42 | unsigned long node, const char *name, | ||
43 | unsigned long *size) | ||
44 | { | ||
45 | unsigned long p = node; | ||
46 | |||
47 | do { | ||
48 | u32 tag = be32_to_cpup((__be32 *)p); | ||
49 | u32 sz, noff; | ||
50 | const char *nstr; | ||
51 | |||
52 | p += 4; | ||
53 | if (tag == OF_DT_NOP) | ||
54 | continue; | ||
55 | if (tag != OF_DT_PROP) | ||
56 | return NULL; | ||
57 | |||
58 | sz = be32_to_cpup((__be32 *)p); | ||
59 | noff = be32_to_cpup((__be32 *)(p + 4)); | ||
60 | p += 8; | ||
61 | if (be32_to_cpu(blob->version) < 0x10) | ||
62 | p = ALIGN(p, sz >= 8 ? 8 : 4); | ||
63 | |||
64 | nstr = of_fdt_get_string(blob, noff); | ||
65 | if (nstr == NULL) { | ||
66 | pr_warning("Can't find property index name !\n"); | ||
67 | return NULL; | ||
68 | } | ||
69 | if (strcmp(name, nstr) == 0) { | ||
70 | if (size) | ||
71 | *size = sz; | ||
72 | return (void *)p; | ||
73 | } | ||
74 | p += sz; | ||
75 | p = ALIGN(p, 4); | ||
76 | } while (1); | ||
77 | } | ||
78 | |||
79 | /** | 29 | /** |
80 | * of_fdt_is_compatible - Return true if given node from the given blob has | 30 | * of_fdt_is_compatible - Return true if given node from the given blob has |
81 | * compat in its compatible list | 31 | * compat in its compatible list |
@@ -86,13 +36,14 @@ void *of_fdt_get_property(struct boot_param_header *blob, | |||
86 | * On match, returns a non-zero value with smaller values returned for more | 36 | * On match, returns a non-zero value with smaller values returned for more |
87 | * specific compatible values. | 37 | * specific compatible values. |
88 | */ | 38 | */ |
89 | int of_fdt_is_compatible(struct boot_param_header *blob, | 39 | int of_fdt_is_compatible(const void *blob, |
90 | unsigned long node, const char *compat) | 40 | unsigned long node, const char *compat) |
91 | { | 41 | { |
92 | const char *cp; | 42 | const char *cp; |
93 | unsigned long cplen, l, score = 0; | 43 | int cplen; |
44 | unsigned long l, score = 0; | ||
94 | 45 | ||
95 | cp = of_fdt_get_property(blob, node, "compatible", &cplen); | 46 | cp = fdt_getprop(blob, node, "compatible", &cplen); |
96 | if (cp == NULL) | 47 | if (cp == NULL) |
97 | return 0; | 48 | return 0; |
98 | while (cplen > 0) { | 49 | while (cplen > 0) { |
@@ -110,7 +61,7 @@ int of_fdt_is_compatible(struct boot_param_header *blob, | |||
110 | /** | 61 | /** |
111 | * of_fdt_match - Return true if node matches a list of compatible values | 62 | * of_fdt_match - Return true if node matches a list of compatible values |
112 | */ | 63 | */ |
113 | int of_fdt_match(struct boot_param_header *blob, unsigned long node, | 64 | int of_fdt_match(const void *blob, unsigned long node, |
114 | const char *const *compat) | 65 | const char *const *compat) |
115 | { | 66 | { |
116 | unsigned int tmp, score = 0; | 67 | unsigned int tmp, score = 0; |
@@ -149,30 +100,29 @@ static void *unflatten_dt_alloc(void **mem, unsigned long size, | |||
149 | * @allnextpp: pointer to ->allnext from last allocated device_node | 100 | * @allnextpp: pointer to ->allnext from last allocated device_node |
150 | * @fpsize: Size of the node path up at the current depth. | 101 | * @fpsize: Size of the node path up at the current depth. |
151 | */ | 102 | */ |
152 | static void * unflatten_dt_node(struct boot_param_header *blob, | 103 | static void * unflatten_dt_node(void *blob, |
153 | void *mem, | 104 | void *mem, |
154 | void **p, | 105 | int *poffset, |
155 | struct device_node *dad, | 106 | struct device_node *dad, |
156 | struct device_node ***allnextpp, | 107 | struct device_node ***allnextpp, |
157 | unsigned long fpsize) | 108 | unsigned long fpsize) |
158 | { | 109 | { |
110 | const __be32 *p; | ||
159 | struct device_node *np; | 111 | struct device_node *np; |
160 | struct property *pp, **prev_pp = NULL; | 112 | struct property *pp, **prev_pp = NULL; |
161 | char *pathp; | 113 | const char *pathp; |
162 | u32 tag; | ||
163 | unsigned int l, allocl; | 114 | unsigned int l, allocl; |
115 | static int depth = 0; | ||
116 | int old_depth; | ||
117 | int offset; | ||
164 | int has_name = 0; | 118 | int has_name = 0; |
165 | int new_format = 0; | 119 | int new_format = 0; |
166 | 120 | ||
167 | tag = be32_to_cpup(*p); | 121 | pathp = fdt_get_name(blob, *poffset, &l); |
168 | if (tag != OF_DT_BEGIN_NODE) { | 122 | if (!pathp) |
169 | pr_err("Weird tag at start of node: %x\n", tag); | ||
170 | return mem; | 123 | return mem; |
171 | } | 124 | |
172 | *p += 4; | 125 | allocl = l++; |
173 | pathp = *p; | ||
174 | l = allocl = strlen(pathp) + 1; | ||
175 | *p = PTR_ALIGN(*p + l, 4); | ||
176 | 126 | ||
177 | /* version 0x10 has a more compact unit name here instead of the full | 127 | /* version 0x10 has a more compact unit name here instead of the full |
178 | * path. we accumulate the full path size using "fpsize", we'll rebuild | 128 | * path. we accumulate the full path size using "fpsize", we'll rebuild |
@@ -190,7 +140,7 @@ static void * unflatten_dt_node(struct boot_param_header *blob, | |||
190 | fpsize = 1; | 140 | fpsize = 1; |
191 | allocl = 2; | 141 | allocl = 2; |
192 | l = 1; | 142 | l = 1; |
193 | *pathp = '\0'; | 143 | pathp = ""; |
194 | } else { | 144 | } else { |
195 | /* account for '/' and path size minus terminal 0 | 145 | /* account for '/' and path size minus terminal 0 |
196 | * already in 'l' | 146 | * already in 'l' |
@@ -237,32 +187,23 @@ static void * unflatten_dt_node(struct boot_param_header *blob, | |||
237 | } | 187 | } |
238 | } | 188 | } |
239 | /* process properties */ | 189 | /* process properties */ |
240 | while (1) { | 190 | for (offset = fdt_first_property_offset(blob, *poffset); |
241 | u32 sz, noff; | 191 | (offset >= 0); |
242 | char *pname; | 192 | (offset = fdt_next_property_offset(blob, offset))) { |
243 | 193 | const char *pname; | |
244 | tag = be32_to_cpup(*p); | 194 | u32 sz; |
245 | if (tag == OF_DT_NOP) { | 195 | |
246 | *p += 4; | 196 | if (!(p = fdt_getprop_by_offset(blob, offset, &pname, &sz))) { |
247 | continue; | 197 | offset = -FDT_ERR_INTERNAL; |
248 | } | ||
249 | if (tag != OF_DT_PROP) | ||
250 | break; | 198 | break; |
251 | *p += 4; | 199 | } |
252 | sz = be32_to_cpup(*p); | 200 | |
253 | noff = be32_to_cpup(*p + 4); | ||
254 | *p += 8; | ||
255 | if (be32_to_cpu(blob->version) < 0x10) | ||
256 | *p = PTR_ALIGN(*p, sz >= 8 ? 8 : 4); | ||
257 | |||
258 | pname = of_fdt_get_string(blob, noff); | ||
259 | if (pname == NULL) { | 201 | if (pname == NULL) { |
260 | pr_info("Can't find property name in list !\n"); | 202 | pr_info("Can't find property name in list !\n"); |
261 | break; | 203 | break; |
262 | } | 204 | } |
263 | if (strcmp(pname, "name") == 0) | 205 | if (strcmp(pname, "name") == 0) |
264 | has_name = 1; | 206 | has_name = 1; |
265 | l = strlen(pname) + 1; | ||
266 | pp = unflatten_dt_alloc(&mem, sizeof(struct property), | 207 | pp = unflatten_dt_alloc(&mem, sizeof(struct property), |
267 | __alignof__(struct property)); | 208 | __alignof__(struct property)); |
268 | if (allnextpp) { | 209 | if (allnextpp) { |
@@ -274,26 +215,25 @@ static void * unflatten_dt_node(struct boot_param_header *blob, | |||
274 | if ((strcmp(pname, "phandle") == 0) || | 215 | if ((strcmp(pname, "phandle") == 0) || |
275 | (strcmp(pname, "linux,phandle") == 0)) { | 216 | (strcmp(pname, "linux,phandle") == 0)) { |
276 | if (np->phandle == 0) | 217 | if (np->phandle == 0) |
277 | np->phandle = be32_to_cpup((__be32*)*p); | 218 | np->phandle = be32_to_cpup(p); |
278 | } | 219 | } |
279 | /* And we process the "ibm,phandle" property | 220 | /* And we process the "ibm,phandle" property |
280 | * used in pSeries dynamic device tree | 221 | * used in pSeries dynamic device tree |
281 | * stuff */ | 222 | * stuff */ |
282 | if (strcmp(pname, "ibm,phandle") == 0) | 223 | if (strcmp(pname, "ibm,phandle") == 0) |
283 | np->phandle = be32_to_cpup((__be32 *)*p); | 224 | np->phandle = be32_to_cpup(p); |
284 | pp->name = pname; | 225 | pp->name = (char *)pname; |
285 | pp->length = sz; | 226 | pp->length = sz; |
286 | pp->value = *p; | 227 | pp->value = (__be32 *)p; |
287 | *prev_pp = pp; | 228 | *prev_pp = pp; |
288 | prev_pp = &pp->next; | 229 | prev_pp = &pp->next; |
289 | } | 230 | } |
290 | *p = PTR_ALIGN((*p) + sz, 4); | ||
291 | } | 231 | } |
292 | /* with version 0x10 we may not have the name property, recreate | 232 | /* with version 0x10 we may not have the name property, recreate |
293 | * it here from the unit name if absent | 233 | * it here from the unit name if absent |
294 | */ | 234 | */ |
295 | if (!has_name) { | 235 | if (!has_name) { |
296 | char *p1 = pathp, *ps = pathp, *pa = NULL; | 236 | const char *p1 = pathp, *ps = pathp, *pa = NULL; |
297 | int sz; | 237 | int sz; |
298 | 238 | ||
299 | while (*p1) { | 239 | while (*p1) { |
@@ -330,19 +270,18 @@ static void * unflatten_dt_node(struct boot_param_header *blob, | |||
330 | if (!np->type) | 270 | if (!np->type) |
331 | np->type = "<NULL>"; | 271 | np->type = "<NULL>"; |
332 | } | 272 | } |
333 | while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) { | 273 | |
334 | if (tag == OF_DT_NOP) | 274 | old_depth = depth; |
335 | *p += 4; | 275 | *poffset = fdt_next_node(blob, *poffset, &depth); |
336 | else | 276 | if (depth < 0) |
337 | mem = unflatten_dt_node(blob, mem, p, np, allnextpp, | 277 | depth = 0; |
338 | fpsize); | 278 | while (*poffset > 0 && depth > old_depth) |
339 | tag = be32_to_cpup(*p); | 279 | mem = unflatten_dt_node(blob, mem, poffset, np, allnextpp, |
340 | } | 280 | fpsize); |
341 | if (tag != OF_DT_END_NODE) { | 281 | |
342 | pr_err("Weird tag at end of node: %x\n", tag); | 282 | if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND) |
343 | return mem; | 283 | pr_err("unflatten: error %d processing FDT\n", *poffset); |
344 | } | 284 | |
345 | *p += 4; | ||
346 | return mem; | 285 | return mem; |
347 | } | 286 | } |
348 | 287 | ||
@@ -358,12 +297,13 @@ static void * unflatten_dt_node(struct boot_param_header *blob, | |||
358 | * @dt_alloc: An allocator that provides a virtual address to memory | 297 | * @dt_alloc: An allocator that provides a virtual address to memory |
359 | * for the resulting tree | 298 | * for the resulting tree |
360 | */ | 299 | */ |
361 | static void __unflatten_device_tree(struct boot_param_header *blob, | 300 | static void __unflatten_device_tree(void *blob, |
362 | struct device_node **mynodes, | 301 | struct device_node **mynodes, |
363 | void * (*dt_alloc)(u64 size, u64 align)) | 302 | void * (*dt_alloc)(u64 size, u64 align)) |
364 | { | 303 | { |
365 | unsigned long size; | 304 | unsigned long size; |
366 | void *start, *mem; | 305 | int start; |
306 | void *mem; | ||
367 | struct device_node **allnextp = mynodes; | 307 | struct device_node **allnextp = mynodes; |
368 | 308 | ||
369 | pr_debug(" -> unflatten_device_tree()\n"); | 309 | pr_debug(" -> unflatten_device_tree()\n"); |
@@ -374,18 +314,18 @@ static void __unflatten_device_tree(struct boot_param_header *blob, | |||
374 | } | 314 | } |
375 | 315 | ||
376 | pr_debug("Unflattening device tree:\n"); | 316 | pr_debug("Unflattening device tree:\n"); |
377 | pr_debug("magic: %08x\n", be32_to_cpu(blob->magic)); | 317 | pr_debug("magic: %08x\n", fdt_magic(blob)); |
378 | pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize)); | 318 | pr_debug("size: %08x\n", fdt_totalsize(blob)); |
379 | pr_debug("version: %08x\n", be32_to_cpu(blob->version)); | 319 | pr_debug("version: %08x\n", fdt_version(blob)); |
380 | 320 | ||
381 | if (be32_to_cpu(blob->magic) != OF_DT_HEADER) { | 321 | if (fdt_check_header(blob)) { |
382 | pr_err("Invalid device tree blob header\n"); | 322 | pr_err("Invalid device tree blob header\n"); |
383 | return; | 323 | return; |
384 | } | 324 | } |
385 | 325 | ||
386 | /* First pass, scan for size */ | 326 | /* First pass, scan for size */ |
387 | start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct); | 327 | start = 0; |
388 | size = (unsigned long)unflatten_dt_node(blob, 0, &start, NULL, NULL, 0); | 328 | size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0); |
389 | size = ALIGN(size, 4); | 329 | size = ALIGN(size, 4); |
390 | 330 | ||
391 | pr_debug(" size is %lx, allocating...\n", size); | 331 | pr_debug(" size is %lx, allocating...\n", size); |
@@ -399,10 +339,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob, | |||
399 | pr_debug(" unflattening %p...\n", mem); | 339 | pr_debug(" unflattening %p...\n", mem); |
400 | 340 | ||
401 | /* Second pass, do actual unflattening */ | 341 | /* Second pass, do actual unflattening */ |
402 | start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct); | 342 | start = 0; |
403 | unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0); | 343 | unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0); |
404 | if (be32_to_cpup(start) != OF_DT_END) | ||
405 | pr_warning("Weird tag at end of tree: %08x\n", be32_to_cpup(start)); | ||
406 | if (be32_to_cpup(mem + size) != 0xdeadbeef) | 344 | if (be32_to_cpup(mem + size) != 0xdeadbeef) |
407 | pr_warning("End of tree marker overwritten: %08x\n", | 345 | pr_warning("End of tree marker overwritten: %08x\n", |
408 | be32_to_cpup(mem + size)); | 346 | be32_to_cpup(mem + size)); |
@@ -427,9 +365,7 @@ static void *kernel_tree_alloc(u64 size, u64 align) | |||
427 | void of_fdt_unflatten_tree(unsigned long *blob, | 365 | void of_fdt_unflatten_tree(unsigned long *blob, |
428 | struct device_node **mynodes) | 366 | struct device_node **mynodes) |
429 | { | 367 | { |
430 | struct boot_param_header *device_tree = | 368 | __unflatten_device_tree(blob, mynodes, &kernel_tree_alloc); |
431 | (struct boot_param_header *)blob; | ||
432 | __unflatten_device_tree(device_tree, mynodes, &kernel_tree_alloc); | ||
433 | } | 369 | } |
434 | EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); | 370 | EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); |
435 | 371 | ||
@@ -437,7 +373,7 @@ EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); | |||
437 | int __initdata dt_root_addr_cells; | 373 | int __initdata dt_root_addr_cells; |
438 | int __initdata dt_root_size_cells; | 374 | int __initdata dt_root_size_cells; |
439 | 375 | ||
440 | struct boot_param_header *initial_boot_params; | 376 | void *initial_boot_params; |
441 | 377 | ||
442 | #ifdef CONFIG_OF_EARLY_FLATTREE | 378 | #ifdef CONFIG_OF_EARLY_FLATTREE |
443 | 379 | ||
@@ -449,8 +385,8 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, | |||
449 | { | 385 | { |
450 | int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); | 386 | int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); |
451 | phys_addr_t base, size; | 387 | phys_addr_t base, size; |
452 | unsigned long len; | 388 | int len; |
453 | __be32 *prop; | 389 | const __be32 *prop; |
454 | int nomap, first = 1; | 390 | int nomap, first = 1; |
455 | 391 | ||
456 | prop = of_get_flat_dt_prop(node, "reg", &len); | 392 | prop = of_get_flat_dt_prop(node, "reg", &len); |
@@ -493,7 +429,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, | |||
493 | */ | 429 | */ |
494 | static int __init __reserved_mem_check_root(unsigned long node) | 430 | static int __init __reserved_mem_check_root(unsigned long node) |
495 | { | 431 | { |
496 | __be32 *prop; | 432 | const __be32 *prop; |
497 | 433 | ||
498 | prop = of_get_flat_dt_prop(node, "#size-cells", NULL); | 434 | prop = of_get_flat_dt_prop(node, "#size-cells", NULL); |
499 | if (!prop || be32_to_cpup(prop) != dt_root_size_cells) | 435 | if (!prop || be32_to_cpup(prop) != dt_root_size_cells) |
@@ -557,9 +493,25 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, | |||
557 | */ | 493 | */ |
558 | void __init early_init_fdt_scan_reserved_mem(void) | 494 | void __init early_init_fdt_scan_reserved_mem(void) |
559 | { | 495 | { |
496 | int n; | ||
497 | u64 base, size; | ||
498 | |||
560 | if (!initial_boot_params) | 499 | if (!initial_boot_params) |
561 | return; | 500 | return; |
562 | 501 | ||
502 | /* Reserve the dtb region */ | ||
503 | early_init_dt_reserve_memory_arch(__pa(initial_boot_params), | ||
504 | fdt_totalsize(initial_boot_params), | ||
505 | 0); | ||
506 | |||
507 | /* Process header /memreserve/ fields */ | ||
508 | for (n = 0; ; n++) { | ||
509 | fdt_get_mem_rsv(initial_boot_params, n, &base, &size); | ||
510 | if (!size) | ||
511 | break; | ||
512 | early_init_dt_reserve_memory_arch(base, size, 0); | ||
513 | } | ||
514 | |||
563 | of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); | 515 | of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); |
564 | fdt_init_reserved_mem(); | 516 | fdt_init_reserved_mem(); |
565 | } | 517 | } |
@@ -578,47 +530,19 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, | |||
578 | void *data), | 530 | void *data), |
579 | void *data) | 531 | void *data) |
580 | { | 532 | { |
581 | unsigned long p = ((unsigned long)initial_boot_params) + | 533 | const void *blob = initial_boot_params; |
582 | be32_to_cpu(initial_boot_params->off_dt_struct); | 534 | const char *pathp; |
583 | int rc = 0; | 535 | int offset, rc = 0, depth = -1; |
584 | int depth = -1; | 536 | |
585 | 537 | for (offset = fdt_next_node(blob, -1, &depth); | |
586 | do { | 538 | offset >= 0 && depth >= 0 && !rc; |
587 | u32 tag = be32_to_cpup((__be32 *)p); | 539 | offset = fdt_next_node(blob, offset, &depth)) { |
588 | const char *pathp; | 540 | |
589 | 541 | pathp = fdt_get_name(blob, offset, NULL); | |
590 | p += 4; | ||
591 | if (tag == OF_DT_END_NODE) { | ||
592 | depth--; | ||
593 | continue; | ||
594 | } | ||
595 | if (tag == OF_DT_NOP) | ||
596 | continue; | ||
597 | if (tag == OF_DT_END) | ||
598 | break; | ||
599 | if (tag == OF_DT_PROP) { | ||
600 | u32 sz = be32_to_cpup((__be32 *)p); | ||
601 | p += 8; | ||
602 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | ||
603 | p = ALIGN(p, sz >= 8 ? 8 : 4); | ||
604 | p += sz; | ||
605 | p = ALIGN(p, 4); | ||
606 | continue; | ||
607 | } | ||
608 | if (tag != OF_DT_BEGIN_NODE) { | ||
609 | pr_err("Invalid tag %x in flat device tree!\n", tag); | ||
610 | return -EINVAL; | ||
611 | } | ||
612 | depth++; | ||
613 | pathp = (char *)p; | ||
614 | p = ALIGN(p + strlen(pathp) + 1, 4); | ||
615 | if (*pathp == '/') | 542 | if (*pathp == '/') |
616 | pathp = kbasename(pathp); | 543 | pathp = kbasename(pathp); |
617 | rc = it(p, pathp, depth, data); | 544 | rc = it(offset, pathp, depth, data); |
618 | if (rc != 0) | 545 | } |
619 | break; | ||
620 | } while (1); | ||
621 | |||
622 | return rc; | 546 | return rc; |
623 | } | 547 | } |
624 | 548 | ||
@@ -627,14 +551,15 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, | |||
627 | */ | 551 | */ |
628 | unsigned long __init of_get_flat_dt_root(void) | 552 | unsigned long __init of_get_flat_dt_root(void) |
629 | { | 553 | { |
630 | unsigned long p = ((unsigned long)initial_boot_params) + | 554 | return 0; |
631 | be32_to_cpu(initial_boot_params->off_dt_struct); | 555 | } |
632 | 556 | ||
633 | while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) | 557 | /** |
634 | p += 4; | 558 | * of_get_flat_dt_size - Return the total size of the FDT |
635 | BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE); | 559 | */ |
636 | p += 4; | 560 | int __init of_get_flat_dt_size(void) |
637 | return ALIGN(p + strlen((char *)p) + 1, 4); | 561 | { |
562 | return fdt_totalsize(initial_boot_params); | ||
638 | } | 563 | } |
639 | 564 | ||
640 | /** | 565 | /** |
@@ -643,10 +568,10 @@ unsigned long __init of_get_flat_dt_root(void) | |||
643 | * This function can be used within scan_flattened_dt callback to get | 568 | * This function can be used within scan_flattened_dt callback to get |
644 | * access to properties | 569 | * access to properties |
645 | */ | 570 | */ |
646 | void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | 571 | const void *__init of_get_flat_dt_prop(unsigned long node, const char *name, |
647 | unsigned long *size) | 572 | int *size) |
648 | { | 573 | { |
649 | return of_fdt_get_property(initial_boot_params, node, name, size); | 574 | return fdt_getprop(initial_boot_params, node, name, size); |
650 | } | 575 | } |
651 | 576 | ||
652 | /** | 577 | /** |
@@ -676,73 +601,6 @@ struct fdt_scan_status { | |||
676 | void *data; | 601 | void *data; |
677 | }; | 602 | }; |
678 | 603 | ||
679 | /** | ||
680 | * fdt_scan_node_by_path - iterator for of_scan_flat_dt_by_path function | ||
681 | */ | ||
682 | static int __init fdt_scan_node_by_path(unsigned long node, const char *uname, | ||
683 | int depth, void *data) | ||
684 | { | ||
685 | struct fdt_scan_status *st = data; | ||
686 | |||
687 | /* | ||
688 | * if scan at the requested fdt node has been completed, | ||
689 | * return -ENXIO to abort further scanning | ||
690 | */ | ||
691 | if (depth <= st->depth) | ||
692 | return -ENXIO; | ||
693 | |||
694 | /* requested fdt node has been found, so call iterator function */ | ||
695 | if (st->found) | ||
696 | return st->iterator(node, uname, depth, st->data); | ||
697 | |||
698 | /* check if scanning automata is entering next level of fdt nodes */ | ||
699 | if (depth == st->depth + 1 && | ||
700 | strncmp(st->name, uname, st->namelen) == 0 && | ||
701 | uname[st->namelen] == 0) { | ||
702 | st->depth += 1; | ||
703 | if (st->name[st->namelen] == 0) { | ||
704 | st->found = 1; | ||
705 | } else { | ||
706 | const char *next = st->name + st->namelen + 1; | ||
707 | st->name = next; | ||
708 | st->namelen = strcspn(next, "/"); | ||
709 | } | ||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | /* scan next fdt node */ | ||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | /** | ||
718 | * of_scan_flat_dt_by_path - scan flattened tree blob and call callback on each | ||
719 | * child of the given path. | ||
720 | * @path: path to start searching for children | ||
721 | * @it: callback function | ||
722 | * @data: context data pointer | ||
723 | * | ||
724 | * This function is used to scan the flattened device-tree starting from the | ||
725 | * node given by path. It is used to extract information (like reserved | ||
726 | * memory), which is required on ealy boot before we can unflatten the tree. | ||
727 | */ | ||
728 | int __init of_scan_flat_dt_by_path(const char *path, | ||
729 | int (*it)(unsigned long node, const char *name, int depth, void *data), | ||
730 | void *data) | ||
731 | { | ||
732 | struct fdt_scan_status st = {path, 0, -1, 0, it, data}; | ||
733 | int ret = 0; | ||
734 | |||
735 | if (initial_boot_params) | ||
736 | ret = of_scan_flat_dt(fdt_scan_node_by_path, &st); | ||
737 | |||
738 | if (!st.found) | ||
739 | return -ENOENT; | ||
740 | else if (ret == -ENXIO) /* scan has been completed */ | ||
741 | return 0; | ||
742 | else | ||
743 | return ret; | ||
744 | } | ||
745 | |||
746 | const char * __init of_flat_dt_get_machine_name(void) | 604 | const char * __init of_flat_dt_get_machine_name(void) |
747 | { | 605 | { |
748 | const char *name; | 606 | const char *name; |
@@ -782,7 +640,7 @@ const void * __init of_flat_dt_match_machine(const void *default_match, | |||
782 | } | 640 | } |
783 | if (!best_data) { | 641 | if (!best_data) { |
784 | const char *prop; | 642 | const char *prop; |
785 | long size; | 643 | int size; |
786 | 644 | ||
787 | pr_err("\n unrecognized device tree list:\n[ "); | 645 | pr_err("\n unrecognized device tree list:\n[ "); |
788 | 646 | ||
@@ -811,8 +669,8 @@ const void * __init of_flat_dt_match_machine(const void *default_match, | |||
811 | static void __init early_init_dt_check_for_initrd(unsigned long node) | 669 | static void __init early_init_dt_check_for_initrd(unsigned long node) |
812 | { | 670 | { |
813 | u64 start, end; | 671 | u64 start, end; |
814 | unsigned long len; | 672 | int len; |
815 | __be32 *prop; | 673 | const __be32 *prop; |
816 | 674 | ||
817 | pr_debug("Looking for initrd properties... "); | 675 | pr_debug("Looking for initrd properties... "); |
818 | 676 | ||
@@ -839,13 +697,68 @@ static inline void early_init_dt_check_for_initrd(unsigned long node) | |||
839 | } | 697 | } |
840 | #endif /* CONFIG_BLK_DEV_INITRD */ | 698 | #endif /* CONFIG_BLK_DEV_INITRD */ |
841 | 699 | ||
700 | #ifdef CONFIG_SERIAL_EARLYCON | ||
701 | extern struct of_device_id __earlycon_of_table[]; | ||
702 | |||
703 | int __init early_init_dt_scan_chosen_serial(void) | ||
704 | { | ||
705 | int offset; | ||
706 | const char *p; | ||
707 | int l; | ||
708 | const struct of_device_id *match = __earlycon_of_table; | ||
709 | const void *fdt = initial_boot_params; | ||
710 | |||
711 | offset = fdt_path_offset(fdt, "/chosen"); | ||
712 | if (offset < 0) | ||
713 | offset = fdt_path_offset(fdt, "/chosen@0"); | ||
714 | if (offset < 0) | ||
715 | return -ENOENT; | ||
716 | |||
717 | p = fdt_getprop(fdt, offset, "stdout-path", &l); | ||
718 | if (!p) | ||
719 | p = fdt_getprop(fdt, offset, "linux,stdout-path", &l); | ||
720 | if (!p || !l) | ||
721 | return -ENOENT; | ||
722 | |||
723 | /* Get the node specified by stdout-path */ | ||
724 | offset = fdt_path_offset(fdt, p); | ||
725 | if (offset < 0) | ||
726 | return -ENODEV; | ||
727 | |||
728 | while (match->compatible) { | ||
729 | unsigned long addr; | ||
730 | if (fdt_node_check_compatible(fdt, offset, match->compatible)) { | ||
731 | match++; | ||
732 | continue; | ||
733 | } | ||
734 | |||
735 | addr = fdt_translate_address(fdt, offset); | ||
736 | if (!addr) | ||
737 | return -ENXIO; | ||
738 | |||
739 | of_setup_earlycon(addr, match->data); | ||
740 | return 0; | ||
741 | } | ||
742 | return -ENODEV; | ||
743 | } | ||
744 | |||
745 | static int __init setup_of_earlycon(char *buf) | ||
746 | { | ||
747 | if (buf) | ||
748 | return 0; | ||
749 | |||
750 | return early_init_dt_scan_chosen_serial(); | ||
751 | } | ||
752 | early_param("earlycon", setup_of_earlycon); | ||
753 | #endif | ||
754 | |||
842 | /** | 755 | /** |
843 | * early_init_dt_scan_root - fetch the top level address and size cells | 756 | * early_init_dt_scan_root - fetch the top level address and size cells |
844 | */ | 757 | */ |
845 | int __init early_init_dt_scan_root(unsigned long node, const char *uname, | 758 | int __init early_init_dt_scan_root(unsigned long node, const char *uname, |
846 | int depth, void *data) | 759 | int depth, void *data) |
847 | { | 760 | { |
848 | __be32 *prop; | 761 | const __be32 *prop; |
849 | 762 | ||
850 | if (depth != 0) | 763 | if (depth != 0) |
851 | return 0; | 764 | return 0; |
@@ -867,9 +780,9 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname, | |||
867 | return 1; | 780 | return 1; |
868 | } | 781 | } |
869 | 782 | ||
870 | u64 __init dt_mem_next_cell(int s, __be32 **cellp) | 783 | u64 __init dt_mem_next_cell(int s, const __be32 **cellp) |
871 | { | 784 | { |
872 | __be32 *p = *cellp; | 785 | const __be32 *p = *cellp; |
873 | 786 | ||
874 | *cellp = p + s; | 787 | *cellp = p + s; |
875 | return of_read_number(p, s); | 788 | return of_read_number(p, s); |
@@ -881,9 +794,9 @@ u64 __init dt_mem_next_cell(int s, __be32 **cellp) | |||
881 | int __init early_init_dt_scan_memory(unsigned long node, const char *uname, | 794 | int __init early_init_dt_scan_memory(unsigned long node, const char *uname, |
882 | int depth, void *data) | 795 | int depth, void *data) |
883 | { | 796 | { |
884 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | 797 | const char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
885 | __be32 *reg, *endp; | 798 | const __be32 *reg, *endp; |
886 | unsigned long l; | 799 | int l; |
887 | 800 | ||
888 | /* We are scanning "memory" nodes only */ | 801 | /* We are scanning "memory" nodes only */ |
889 | if (type == NULL) { | 802 | if (type == NULL) { |
@@ -891,7 +804,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, | |||
891 | * The longtrail doesn't have a device_type on the | 804 | * The longtrail doesn't have a device_type on the |
892 | * /memory node, so look for the node called /memory@0. | 805 | * /memory node, so look for the node called /memory@0. |
893 | */ | 806 | */ |
894 | if (depth != 1 || strcmp(uname, "memory@0") != 0) | 807 | if (!IS_ENABLED(CONFIG_PPC32) || depth != 1 || strcmp(uname, "memory@0") != 0) |
895 | return 0; | 808 | return 0; |
896 | } else if (strcmp(type, "memory") != 0) | 809 | } else if (strcmp(type, "memory") != 0) |
897 | return 0; | 810 | return 0; |
@@ -904,7 +817,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, | |||
904 | 817 | ||
905 | endp = reg + (l / sizeof(__be32)); | 818 | endp = reg + (l / sizeof(__be32)); |
906 | 819 | ||
907 | pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", | 820 | pr_debug("memory scan node %s, reg size %d, data: %x %x %x %x,\n", |
908 | uname, l, reg[0], reg[1], reg[2], reg[3]); | 821 | uname, l, reg[0], reg[1], reg[2], reg[3]); |
909 | 822 | ||
910 | while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { | 823 | while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { |
@@ -927,8 +840,8 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, | |||
927 | int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | 840 | int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, |
928 | int depth, void *data) | 841 | int depth, void *data) |
929 | { | 842 | { |
930 | unsigned long l; | 843 | int l; |
931 | char *p; | 844 | const char *p; |
932 | 845 | ||
933 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); | 846 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); |
934 | 847 | ||
@@ -1003,8 +916,8 @@ void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align) | |||
1003 | int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, | 916 | int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, |
1004 | phys_addr_t size, bool nomap) | 917 | phys_addr_t size, bool nomap) |
1005 | { | 918 | { |
1006 | pr_err("Reserved memory not supported, ignoring range 0x%llx - 0x%llx%s\n", | 919 | pr_err("Reserved memory not supported, ignoring range 0x%pa - 0x%pa%s\n", |
1007 | base, size, nomap ? " (nomap)" : ""); | 920 | &base, &size, nomap ? " (nomap)" : ""); |
1008 | return -ENOSYS; | 921 | return -ENOSYS; |
1009 | } | 922 | } |
1010 | #endif | 923 | #endif |
@@ -1018,7 +931,7 @@ bool __init early_init_dt_scan(void *params) | |||
1018 | initial_boot_params = params; | 931 | initial_boot_params = params; |
1019 | 932 | ||
1020 | /* check device tree validity */ | 933 | /* check device tree validity */ |
1021 | if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) { | 934 | if (fdt_check_header(params)) { |
1022 | initial_boot_params = NULL; | 935 | initial_boot_params = NULL; |
1023 | return false; | 936 | return false; |
1024 | } | 937 | } |
@@ -1073,9 +986,9 @@ void __init unflatten_and_copy_device_tree(void) | |||
1073 | return; | 986 | return; |
1074 | } | 987 | } |
1075 | 988 | ||
1076 | size = __be32_to_cpu(initial_boot_params->totalsize); | 989 | size = fdt_totalsize(initial_boot_params); |
1077 | dt = early_init_dt_alloc_memory_arch(size, | 990 | dt = early_init_dt_alloc_memory_arch(size, |
1078 | __alignof__(struct boot_param_header)); | 991 | roundup_pow_of_two(FDT_V17_SIZE)); |
1079 | 992 | ||
1080 | if (dt) { | 993 | if (dt) { |
1081 | memcpy(dt, initial_boot_params, size); | 994 | memcpy(dt, initial_boot_params, size); |
@@ -1084,4 +997,27 @@ void __init unflatten_and_copy_device_tree(void) | |||
1084 | unflatten_device_tree(); | 997 | unflatten_device_tree(); |
1085 | } | 998 | } |
1086 | 999 | ||
1000 | #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) | ||
1001 | static struct debugfs_blob_wrapper flat_dt_blob; | ||
1002 | |||
1003 | static int __init of_flat_dt_debugfs_export_fdt(void) | ||
1004 | { | ||
1005 | struct dentry *d = debugfs_create_dir("device-tree", NULL); | ||
1006 | |||
1007 | if (!d) | ||
1008 | return -ENOENT; | ||
1009 | |||
1010 | flat_dt_blob.data = initial_boot_params; | ||
1011 | flat_dt_blob.size = fdt_totalsize(initial_boot_params); | ||
1012 | |||
1013 | d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR, | ||
1014 | d, &flat_dt_blob); | ||
1015 | if (!d) | ||
1016 | return -ENOENT; | ||
1017 | |||
1018 | return 0; | ||
1019 | } | ||
1020 | module_init(of_flat_dt_debugfs_export_fdt); | ||
1021 | #endif | ||
1022 | |||
1087 | #endif /* CONFIG_OF_EARLY_FLATTREE */ | 1023 | #endif /* CONFIG_OF_EARLY_FLATTREE */ |
diff --git a/drivers/of/fdt_address.c b/drivers/of/fdt_address.c new file mode 100644 index 000000000000..8d3dc6fbdb7a --- /dev/null +++ b/drivers/of/fdt_address.c | |||
@@ -0,0 +1,241 @@ | |||
1 | /* | ||
2 | * FDT Address translation based on u-boot fdt_support.c which in turn was | ||
3 | * based on the kernel unflattened DT address translation code. | ||
4 | * | ||
5 | * (C) Copyright 2007 | ||
6 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com | ||
7 | * | ||
8 | * Copyright 2010-2011 Freescale Semiconductor, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2, or (at your option) | ||
13 | * any later version. | ||
14 | */ | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/libfdt.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/of_fdt.h> | ||
19 | #include <linux/sizes.h> | ||
20 | |||
21 | /* Max address size we deal with */ | ||
22 | #define OF_MAX_ADDR_CELLS 4 | ||
23 | #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ | ||
24 | (ns) > 0) | ||
25 | |||
26 | /* Debug utility */ | ||
27 | #ifdef DEBUG | ||
28 | static void __init of_dump_addr(const char *s, const __be32 *addr, int na) | ||
29 | { | ||
30 | pr_debug("%s", s); | ||
31 | while(na--) | ||
32 | pr_cont(" %08x", *(addr++)); | ||
33 | pr_debug("\n"); | ||
34 | } | ||
35 | #else | ||
36 | static void __init of_dump_addr(const char *s, const __be32 *addr, int na) { } | ||
37 | #endif | ||
38 | |||
39 | /* Callbacks for bus specific translators */ | ||
40 | struct of_bus { | ||
41 | void (*count_cells)(const void *blob, int parentoffset, | ||
42 | int *addrc, int *sizec); | ||
43 | u64 (*map)(__be32 *addr, const __be32 *range, | ||
44 | int na, int ns, int pna); | ||
45 | int (*translate)(__be32 *addr, u64 offset, int na); | ||
46 | }; | ||
47 | |||
48 | /* Default translator (generic bus) */ | ||
49 | static void __init fdt_bus_default_count_cells(const void *blob, int parentoffset, | ||
50 | int *addrc, int *sizec) | ||
51 | { | ||
52 | const __be32 *prop; | ||
53 | |||
54 | if (addrc) { | ||
55 | prop = fdt_getprop(blob, parentoffset, "#address-cells", NULL); | ||
56 | if (prop) | ||
57 | *addrc = be32_to_cpup(prop); | ||
58 | else | ||
59 | *addrc = dt_root_addr_cells; | ||
60 | } | ||
61 | |||
62 | if (sizec) { | ||
63 | prop = fdt_getprop(blob, parentoffset, "#size-cells", NULL); | ||
64 | if (prop) | ||
65 | *sizec = be32_to_cpup(prop); | ||
66 | else | ||
67 | *sizec = dt_root_size_cells; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | static u64 __init fdt_bus_default_map(__be32 *addr, const __be32 *range, | ||
72 | int na, int ns, int pna) | ||
73 | { | ||
74 | u64 cp, s, da; | ||
75 | |||
76 | cp = of_read_number(range, na); | ||
77 | s = of_read_number(range + na + pna, ns); | ||
78 | da = of_read_number(addr, na); | ||
79 | |||
80 | pr_debug("FDT: default map, cp=%llx, s=%llx, da=%llx\n", | ||
81 | cp, s, da); | ||
82 | |||
83 | if (da < cp || da >= (cp + s)) | ||
84 | return OF_BAD_ADDR; | ||
85 | return da - cp; | ||
86 | } | ||
87 | |||
88 | static int __init fdt_bus_default_translate(__be32 *addr, u64 offset, int na) | ||
89 | { | ||
90 | u64 a = of_read_number(addr, na); | ||
91 | memset(addr, 0, na * 4); | ||
92 | a += offset; | ||
93 | if (na > 1) | ||
94 | addr[na - 2] = cpu_to_fdt32(a >> 32); | ||
95 | addr[na - 1] = cpu_to_fdt32(a & 0xffffffffu); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | /* Array of bus specific translators */ | ||
101 | static const struct of_bus of_busses[] __initconst = { | ||
102 | /* Default */ | ||
103 | { | ||
104 | .count_cells = fdt_bus_default_count_cells, | ||
105 | .map = fdt_bus_default_map, | ||
106 | .translate = fdt_bus_default_translate, | ||
107 | }, | ||
108 | }; | ||
109 | |||
110 | static int __init fdt_translate_one(const void *blob, int parent, | ||
111 | const struct of_bus *bus, | ||
112 | const struct of_bus *pbus, __be32 *addr, | ||
113 | int na, int ns, int pna, const char *rprop) | ||
114 | { | ||
115 | const __be32 *ranges; | ||
116 | int rlen; | ||
117 | int rone; | ||
118 | u64 offset = OF_BAD_ADDR; | ||
119 | |||
120 | ranges = fdt_getprop(blob, parent, rprop, &rlen); | ||
121 | if (!ranges) | ||
122 | return 1; | ||
123 | if (rlen == 0) { | ||
124 | offset = of_read_number(addr, na); | ||
125 | memset(addr, 0, pna * 4); | ||
126 | pr_debug("FDT: empty ranges, 1:1 translation\n"); | ||
127 | goto finish; | ||
128 | } | ||
129 | |||
130 | pr_debug("FDT: walking ranges...\n"); | ||
131 | |||
132 | /* Now walk through the ranges */ | ||
133 | rlen /= 4; | ||
134 | rone = na + pna + ns; | ||
135 | for (; rlen >= rone; rlen -= rone, ranges += rone) { | ||
136 | offset = bus->map(addr, ranges, na, ns, pna); | ||
137 | if (offset != OF_BAD_ADDR) | ||
138 | break; | ||
139 | } | ||
140 | if (offset == OF_BAD_ADDR) { | ||
141 | pr_debug("FDT: not found !\n"); | ||
142 | return 1; | ||
143 | } | ||
144 | memcpy(addr, ranges + na, 4 * pna); | ||
145 | |||
146 | finish: | ||
147 | of_dump_addr("FDT: parent translation for:", addr, pna); | ||
148 | pr_debug("FDT: with offset: %llx\n", offset); | ||
149 | |||
150 | /* Translate it into parent bus space */ | ||
151 | return pbus->translate(addr, offset, pna); | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Translate an address from the device-tree into a CPU physical address, | ||
156 | * this walks up the tree and applies the various bus mappings on the | ||
157 | * way. | ||
158 | * | ||
159 | * Note: We consider that crossing any level with #size-cells == 0 to mean | ||
160 | * that translation is impossible (that is we are not dealing with a value | ||
161 | * that can be mapped to a cpu physical address). This is not really specified | ||
162 | * that way, but this is traditionally the way IBM at least do things | ||
163 | */ | ||
164 | u64 __init fdt_translate_address(const void *blob, int node_offset) | ||
165 | { | ||
166 | int parent, len; | ||
167 | const struct of_bus *bus, *pbus; | ||
168 | const __be32 *reg; | ||
169 | __be32 addr[OF_MAX_ADDR_CELLS]; | ||
170 | int na, ns, pna, pns; | ||
171 | u64 result = OF_BAD_ADDR; | ||
172 | |||
173 | pr_debug("FDT: ** translation for device %s **\n", | ||
174 | fdt_get_name(blob, node_offset, NULL)); | ||
175 | |||
176 | reg = fdt_getprop(blob, node_offset, "reg", &len); | ||
177 | if (!reg) { | ||
178 | pr_err("FDT: warning: device tree node '%s' has no address.\n", | ||
179 | fdt_get_name(blob, node_offset, NULL)); | ||
180 | goto bail; | ||
181 | } | ||
182 | |||
183 | /* Get parent & match bus type */ | ||
184 | parent = fdt_parent_offset(blob, node_offset); | ||
185 | if (parent < 0) | ||
186 | goto bail; | ||
187 | bus = &of_busses[0]; | ||
188 | |||
189 | /* Cound address cells & copy address locally */ | ||
190 | bus->count_cells(blob, parent, &na, &ns); | ||
191 | if (!OF_CHECK_COUNTS(na, ns)) { | ||
192 | pr_err("FDT: Bad cell count for %s\n", | ||
193 | fdt_get_name(blob, node_offset, NULL)); | ||
194 | goto bail; | ||
195 | } | ||
196 | memcpy(addr, reg, na * 4); | ||
197 | |||
198 | pr_debug("FDT: bus (na=%d, ns=%d) on %s\n", | ||
199 | na, ns, fdt_get_name(blob, parent, NULL)); | ||
200 | of_dump_addr("OF: translating address:", addr, na); | ||
201 | |||
202 | /* Translate */ | ||
203 | for (;;) { | ||
204 | /* Switch to parent bus */ | ||
205 | node_offset = parent; | ||
206 | parent = fdt_parent_offset(blob, node_offset); | ||
207 | |||
208 | /* If root, we have finished */ | ||
209 | if (parent < 0) { | ||
210 | pr_debug("FDT: reached root node\n"); | ||
211 | result = of_read_number(addr, na); | ||
212 | break; | ||
213 | } | ||
214 | |||
215 | /* Get new parent bus and counts */ | ||
216 | pbus = &of_busses[0]; | ||
217 | pbus->count_cells(blob, parent, &pna, &pns); | ||
218 | if (!OF_CHECK_COUNTS(pna, pns)) { | ||
219 | pr_err("FDT: Bad cell count for %s\n", | ||
220 | fdt_get_name(blob, node_offset, NULL)); | ||
221 | break; | ||
222 | } | ||
223 | |||
224 | pr_debug("FDT: parent bus (na=%d, ns=%d) on %s\n", | ||
225 | pna, pns, fdt_get_name(blob, parent, NULL)); | ||
226 | |||
227 | /* Apply bus translation */ | ||
228 | if (fdt_translate_one(blob, node_offset, bus, pbus, | ||
229 | addr, na, ns, pna, "ranges")) | ||
230 | break; | ||
231 | |||
232 | /* Complete the move up one level */ | ||
233 | na = pna; | ||
234 | ns = pns; | ||
235 | bus = pbus; | ||
236 | |||
237 | of_dump_addr("FDT: one level translation:", addr, na); | ||
238 | } | ||
239 | bail: | ||
240 | return result; | ||
241 | } | ||
diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 5aeb89411350..3e06a699352d 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c | |||
@@ -406,6 +406,28 @@ int of_irq_get(struct device_node *dev, int index) | |||
406 | } | 406 | } |
407 | 407 | ||
408 | /** | 408 | /** |
409 | * of_irq_get_byname - Decode a node's IRQ and return it as a Linux irq number | ||
410 | * @dev: pointer to device tree node | ||
411 | * @name: irq name | ||
412 | * | ||
413 | * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain | ||
414 | * is not yet created, or error code in case of any other failure. | ||
415 | */ | ||
416 | int of_irq_get_byname(struct device_node *dev, const char *name) | ||
417 | { | ||
418 | int index; | ||
419 | |||
420 | if (unlikely(!name)) | ||
421 | return -EINVAL; | ||
422 | |||
423 | index = of_property_match_string(dev, "interrupt-names", name); | ||
424 | if (index < 0) | ||
425 | return index; | ||
426 | |||
427 | return of_irq_get(dev, index); | ||
428 | } | ||
429 | |||
430 | /** | ||
409 | * of_irq_count - Count the number of IRQs a node uses | 431 | * of_irq_count - Count the number of IRQs a node uses |
410 | * @dev: pointer to device tree node | 432 | * @dev: pointer to device tree node |
411 | */ | 433 | */ |
diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c index 8736bc7676c5..1710d9dc7fc2 100644 --- a/drivers/of/of_pci_irq.c +++ b/drivers/of/of_pci_irq.c | |||
@@ -18,8 +18,6 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq | |||
18 | { | 18 | { |
19 | struct device_node *dn, *ppnode; | 19 | struct device_node *dn, *ppnode; |
20 | struct pci_dev *ppdev; | 20 | struct pci_dev *ppdev; |
21 | u32 lspec; | ||
22 | __be32 lspec_be; | ||
23 | __be32 laddr[3]; | 21 | __be32 laddr[3]; |
24 | u8 pin; | 22 | u8 pin; |
25 | int rc; | 23 | int rc; |
@@ -46,7 +44,6 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq | |||
46 | return -ENODEV; | 44 | return -ENODEV; |
47 | 45 | ||
48 | /* Now we walk up the PCI tree */ | 46 | /* Now we walk up the PCI tree */ |
49 | lspec = pin; | ||
50 | for (;;) { | 47 | for (;;) { |
51 | /* Get the pci_dev of our parent */ | 48 | /* Get the pci_dev of our parent */ |
52 | ppdev = pdev->bus->self; | 49 | ppdev = pdev->bus->self; |
@@ -80,14 +77,13 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq | |||
80 | /* We can only get here if we hit a P2P bridge with no node, | 77 | /* We can only get here if we hit a P2P bridge with no node, |
81 | * let's do standard swizzling and try again | 78 | * let's do standard swizzling and try again |
82 | */ | 79 | */ |
83 | lspec = pci_swizzle_interrupt_pin(pdev, lspec); | 80 | pin = pci_swizzle_interrupt_pin(pdev, pin); |
84 | pdev = ppdev; | 81 | pdev = ppdev; |
85 | } | 82 | } |
86 | 83 | ||
87 | out_irq->np = ppnode; | 84 | out_irq->np = ppnode; |
88 | out_irq->args_count = 1; | 85 | out_irq->args_count = 1; |
89 | out_irq->args[0] = lspec; | 86 | out_irq->args[0] = pin; |
90 | lspec_be = cpu_to_be32(lspec); | ||
91 | laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); | 87 | laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); |
92 | laddr[1] = laddr[2] = cpu_to_be32(0); | 88 | laddr[1] = laddr[2] = cpu_to_be32(0); |
93 | return of_irq_parse_raw(laddr, out_irq); | 89 | return of_irq_parse_raw(laddr, out_irq); |
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index daaaf935911d..632aae861375 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c | |||
@@ -95,8 +95,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node, | |||
95 | int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); | 95 | int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); |
96 | phys_addr_t start = 0, end = 0; | 96 | phys_addr_t start = 0, end = 0; |
97 | phys_addr_t base = 0, align = 0, size; | 97 | phys_addr_t base = 0, align = 0, size; |
98 | unsigned long len; | 98 | int len; |
99 | __be32 *prop; | 99 | const __be32 *prop; |
100 | int nomap; | 100 | int nomap; |
101 | int ret; | 101 | int ret; |
102 | 102 | ||
@@ -188,7 +188,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) | |||
188 | if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) | 188 | if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) |
189 | continue; | 189 | continue; |
190 | 190 | ||
191 | if (initfn(rmem, rmem->fdt_node, rmem->name) == 0) { | 191 | if (initfn(rmem) == 0) { |
192 | pr_info("Reserved memory: initialized node %s, compatible id %s\n", | 192 | pr_info("Reserved memory: initialized node %s, compatible id %s\n", |
193 | rmem->name, compat); | 193 | rmem->name, compat); |
194 | return 0; | 194 | return 0; |
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index e8376d646d98..92c060e58b02 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -51,10 +51,6 @@ struct platform_device *of_find_device_by_node(struct device_node *np) | |||
51 | } | 51 | } |
52 | EXPORT_SYMBOL(of_find_device_by_node); | 52 | EXPORT_SYMBOL(of_find_device_by_node); |
53 | 53 | ||
54 | #if defined(CONFIG_PPC_DCR) | ||
55 | #include <asm/dcr.h> | ||
56 | #endif | ||
57 | |||
58 | #ifdef CONFIG_OF_ADDRESS | 54 | #ifdef CONFIG_OF_ADDRESS |
59 | /* | 55 | /* |
60 | * The following routines scan a subtree and registers a device for | 56 | * The following routines scan a subtree and registers a device for |
@@ -68,66 +64,35 @@ EXPORT_SYMBOL(of_find_device_by_node); | |||
68 | * of_device_make_bus_id - Use the device node data to assign a unique name | 64 | * of_device_make_bus_id - Use the device node data to assign a unique name |
69 | * @dev: pointer to device structure that is linked to a device tree node | 65 | * @dev: pointer to device structure that is linked to a device tree node |
70 | * | 66 | * |
71 | * This routine will first try using either the dcr-reg or the reg property | 67 | * This routine will first try using the translated bus address to |
72 | * value to derive a unique name. As a last resort it will use the node | 68 | * derive a unique name. If it cannot, then it will prepend names from |
73 | * name followed by a unique number. | 69 | * parent nodes until a unique name can be derived. |
74 | */ | 70 | */ |
75 | void of_device_make_bus_id(struct device *dev) | 71 | void of_device_make_bus_id(struct device *dev) |
76 | { | 72 | { |
77 | static atomic_t bus_no_reg_magic; | ||
78 | struct device_node *node = dev->of_node; | 73 | struct device_node *node = dev->of_node; |
79 | const __be32 *reg; | 74 | const __be32 *reg; |
80 | u64 addr; | 75 | u64 addr; |
81 | const __be32 *addrp; | ||
82 | int magic; | ||
83 | 76 | ||
84 | #ifdef CONFIG_PPC_DCR | 77 | /* Construct the name, using parent nodes if necessary to ensure uniqueness */ |
85 | /* | 78 | while (node->parent) { |
86 | * If it's a DCR based device, use 'd' for native DCRs | 79 | /* |
87 | * and 'D' for MMIO DCRs. | 80 | * If the address can be translated, then that is as much |
88 | */ | 81 | * uniqueness as we need. Make it the first component and return |
89 | reg = of_get_property(node, "dcr-reg", NULL); | 82 | */ |
90 | if (reg) { | 83 | reg = of_get_property(node, "reg", NULL); |
91 | #ifdef CONFIG_PPC_DCR_NATIVE | 84 | if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) { |
92 | dev_set_name(dev, "d%x.%s", *reg, node->name); | 85 | dev_set_name(dev, dev_name(dev) ? "%llx.%s:%s" : "%llx.%s", |
93 | #else /* CONFIG_PPC_DCR_NATIVE */ | 86 | (unsigned long long)addr, node->name, |
94 | u64 addr = of_translate_dcr_address(node, *reg, NULL); | 87 | dev_name(dev)); |
95 | if (addr != OF_BAD_ADDR) { | ||
96 | dev_set_name(dev, "D%llx.%s", | ||
97 | (unsigned long long)addr, node->name); | ||
98 | return; | 88 | return; |
99 | } | 89 | } |
100 | #endif /* !CONFIG_PPC_DCR_NATIVE */ | ||
101 | } | ||
102 | #endif /* CONFIG_PPC_DCR */ | ||
103 | 90 | ||
104 | /* | 91 | /* format arguments only used if dev_name() resolves to NULL */ |
105 | * For MMIO, get the physical address | 92 | dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s", |
106 | */ | 93 | strrchr(node->full_name, '/') + 1, dev_name(dev)); |
107 | reg = of_get_property(node, "reg", NULL); | 94 | node = node->parent; |
108 | if (reg) { | ||
109 | if (of_can_translate_address(node)) { | ||
110 | addr = of_translate_address(node, reg); | ||
111 | } else { | ||
112 | addrp = of_get_address(node, 0, NULL, NULL); | ||
113 | if (addrp) | ||
114 | addr = of_read_number(addrp, 1); | ||
115 | else | ||
116 | addr = OF_BAD_ADDR; | ||
117 | } | ||
118 | if (addr != OF_BAD_ADDR) { | ||
119 | dev_set_name(dev, "%llx.%s", | ||
120 | (unsigned long long)addr, node->name); | ||
121 | return; | ||
122 | } | ||
123 | } | 95 | } |
124 | |||
125 | /* | ||
126 | * No BusID, use the node name and add a globally incremented | ||
127 | * counter (and pray...) | ||
128 | */ | ||
129 | magic = atomic_add_return(1, &bus_no_reg_magic); | ||
130 | dev_set_name(dev, "%s.%d", node->name, magic - 1); | ||
131 | } | 96 | } |
132 | 97 | ||
133 | /** | 98 | /** |
@@ -149,9 +114,8 @@ struct platform_device *of_device_alloc(struct device_node *np, | |||
149 | return NULL; | 114 | return NULL; |
150 | 115 | ||
151 | /* count the io and irq resources */ | 116 | /* count the io and irq resources */ |
152 | if (of_can_translate_address(np)) | 117 | while (of_address_to_resource(np, num_reg, &temp_res) == 0) |
153 | while (of_address_to_resource(np, num_reg, &temp_res) == 0) | 118 | num_reg++; |
154 | num_reg++; | ||
155 | num_irq = of_irq_count(np); | 119 | num_irq = of_irq_count(np); |
156 | 120 | ||
157 | /* Populate the resource table */ | 121 | /* Populate the resource table */ |
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index fe70b86bcffb..077314eebb95 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c | |||
@@ -31,6 +31,51 @@ static struct selftest_results { | |||
31 | } \ | 31 | } \ |
32 | } | 32 | } |
33 | 33 | ||
34 | static void __init of_selftest_find_node_by_name(void) | ||
35 | { | ||
36 | struct device_node *np; | ||
37 | |||
38 | np = of_find_node_by_path("/testcase-data"); | ||
39 | selftest(np && !strcmp("/testcase-data", np->full_name), | ||
40 | "find /testcase-data failed\n"); | ||
41 | of_node_put(np); | ||
42 | |||
43 | /* Test if trailing '/' works */ | ||
44 | np = of_find_node_by_path("/testcase-data/"); | ||
45 | selftest(!np, "trailing '/' on /testcase-data/ should fail\n"); | ||
46 | |||
47 | np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); | ||
48 | selftest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name), | ||
49 | "find /testcase-data/phandle-tests/consumer-a failed\n"); | ||
50 | of_node_put(np); | ||
51 | |||
52 | np = of_find_node_by_path("testcase-alias"); | ||
53 | selftest(np && !strcmp("/testcase-data", np->full_name), | ||
54 | "find testcase-alias failed\n"); | ||
55 | of_node_put(np); | ||
56 | |||
57 | /* Test if trailing '/' works on aliases */ | ||
58 | np = of_find_node_by_path("testcase-alias/"); | ||
59 | selftest(!np, "trailing '/' on testcase-alias/ should fail\n"); | ||
60 | |||
61 | np = of_find_node_by_path("testcase-alias/phandle-tests/consumer-a"); | ||
62 | selftest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name), | ||
63 | "find testcase-alias/phandle-tests/consumer-a failed\n"); | ||
64 | of_node_put(np); | ||
65 | |||
66 | np = of_find_node_by_path("/testcase-data/missing-path"); | ||
67 | selftest(!np, "non-existent path returned node %s\n", np->full_name); | ||
68 | of_node_put(np); | ||
69 | |||
70 | np = of_find_node_by_path("missing-alias"); | ||
71 | selftest(!np, "non-existent alias returned node %s\n", np->full_name); | ||
72 | of_node_put(np); | ||
73 | |||
74 | np = of_find_node_by_path("testcase-alias/missing-path"); | ||
75 | selftest(!np, "non-existent alias with relative path returned node %s\n", np->full_name); | ||
76 | of_node_put(np); | ||
77 | } | ||
78 | |||
34 | static void __init of_selftest_dynamic(void) | 79 | static void __init of_selftest_dynamic(void) |
35 | { | 80 | { |
36 | struct device_node *np; | 81 | struct device_node *np; |
@@ -431,8 +476,12 @@ static void __init of_selftest_match_node(void) | |||
431 | static void __init of_selftest_platform_populate(void) | 476 | static void __init of_selftest_platform_populate(void) |
432 | { | 477 | { |
433 | int irq; | 478 | int irq; |
434 | struct device_node *np; | 479 | struct device_node *np, *child; |
435 | struct platform_device *pdev; | 480 | struct platform_device *pdev; |
481 | struct of_device_id match[] = { | ||
482 | { .compatible = "test-device", }, | ||
483 | {} | ||
484 | }; | ||
436 | 485 | ||
437 | np = of_find_node_by_path("/testcase-data"); | 486 | np = of_find_node_by_path("/testcase-data"); |
438 | of_platform_populate(np, of_default_bus_match_table, NULL, NULL); | 487 | of_platform_populate(np, of_default_bus_match_table, NULL, NULL); |
@@ -440,22 +489,32 @@ static void __init of_selftest_platform_populate(void) | |||
440 | /* Test that a missing irq domain returns -EPROBE_DEFER */ | 489 | /* Test that a missing irq domain returns -EPROBE_DEFER */ |
441 | np = of_find_node_by_path("/testcase-data/testcase-device1"); | 490 | np = of_find_node_by_path("/testcase-data/testcase-device1"); |
442 | pdev = of_find_device_by_node(np); | 491 | pdev = of_find_device_by_node(np); |
443 | if (!pdev) | 492 | selftest(pdev, "device 1 creation failed\n"); |
444 | selftest(0, "device 1 creation failed\n"); | 493 | |
445 | irq = platform_get_irq(pdev, 0); | 494 | irq = platform_get_irq(pdev, 0); |
446 | if (irq != -EPROBE_DEFER) | 495 | selftest(irq == -EPROBE_DEFER, "device deferred probe failed - %d\n", irq); |
447 | selftest(0, "device deferred probe failed - %d\n", irq); | ||
448 | 496 | ||
449 | /* Test that a parsing failure does not return -EPROBE_DEFER */ | 497 | /* Test that a parsing failure does not return -EPROBE_DEFER */ |
450 | np = of_find_node_by_path("/testcase-data/testcase-device2"); | 498 | np = of_find_node_by_path("/testcase-data/testcase-device2"); |
451 | pdev = of_find_device_by_node(np); | 499 | pdev = of_find_device_by_node(np); |
452 | if (!pdev) | 500 | selftest(pdev, "device 2 creation failed\n"); |
453 | selftest(0, "device 2 creation failed\n"); | ||
454 | irq = platform_get_irq(pdev, 0); | 501 | irq = platform_get_irq(pdev, 0); |
455 | if (irq >= 0 || irq == -EPROBE_DEFER) | 502 | selftest(irq < 0 && irq != -EPROBE_DEFER, "device parsing error failed - %d\n", irq); |
456 | selftest(0, "device parsing error failed - %d\n", irq); | ||
457 | 503 | ||
458 | selftest(1, "passed"); | 504 | np = of_find_node_by_path("/testcase-data/platform-tests"); |
505 | if (!np) { | ||
506 | pr_err("No testcase data in device tree\n"); | ||
507 | return; | ||
508 | } | ||
509 | |||
510 | for_each_child_of_node(np, child) { | ||
511 | struct device_node *grandchild; | ||
512 | of_platform_populate(child, match, NULL, NULL); | ||
513 | for_each_child_of_node(child, grandchild) | ||
514 | selftest(of_find_device_by_node(grandchild), | ||
515 | "Could not create device for node '%s'\n", | ||
516 | grandchild->name); | ||
517 | } | ||
459 | } | 518 | } |
460 | 519 | ||
461 | static int __init of_selftest(void) | 520 | static int __init of_selftest(void) |
@@ -470,6 +529,7 @@ static int __init of_selftest(void) | |||
470 | of_node_put(np); | 529 | of_node_put(np); |
471 | 530 | ||
472 | pr_info("start of selftest - you will see error messages\n"); | 531 | pr_info("start of selftest - you will see error messages\n"); |
532 | of_selftest_find_node_by_name(); | ||
473 | of_selftest_dynamic(); | 533 | of_selftest_dynamic(); |
474 | of_selftest_parse_phandle_with_args(); | 534 | of_selftest_parse_phandle_with_args(); |
475 | of_selftest_property_match_string(); | 535 | of_selftest_property_match_string(); |
diff --git a/drivers/of/testcase-data/testcases.dtsi b/drivers/of/testcase-data/testcases.dtsi index 3a5b75a8e4d7..6d8d980ac858 100644 --- a/drivers/of/testcase-data/testcases.dtsi +++ b/drivers/of/testcase-data/testcases.dtsi | |||
@@ -1,3 +1,4 @@ | |||
1 | #include "tests-phandle.dtsi" | 1 | #include "tests-phandle.dtsi" |
2 | #include "tests-interrupts.dtsi" | 2 | #include "tests-interrupts.dtsi" |
3 | #include "tests-match.dtsi" | 3 | #include "tests-match.dtsi" |
4 | #include "tests-platform.dtsi" | ||
diff --git a/drivers/of/testcase-data/tests-phandle.dtsi b/drivers/of/testcase-data/tests-phandle.dtsi index 788a4c24b8f5..ce0fe083d406 100644 --- a/drivers/of/testcase-data/tests-phandle.dtsi +++ b/drivers/of/testcase-data/tests-phandle.dtsi | |||
@@ -1,6 +1,10 @@ | |||
1 | 1 | ||
2 | / { | 2 | / { |
3 | testcase-data { | 3 | aliases { |
4 | testcase-alias = &testcase; | ||
5 | }; | ||
6 | |||
7 | testcase: testcase-data { | ||
4 | security-password = "password"; | 8 | security-password = "password"; |
5 | duplicate-name = "duplicate"; | 9 | duplicate-name = "duplicate"; |
6 | duplicate-name { }; | 10 | duplicate-name { }; |
diff --git a/drivers/of/testcase-data/tests-platform.dtsi b/drivers/of/testcase-data/tests-platform.dtsi new file mode 100644 index 000000000000..eb20eeb2b062 --- /dev/null +++ b/drivers/of/testcase-data/tests-platform.dtsi | |||
@@ -0,0 +1,35 @@ | |||
1 | |||
2 | / { | ||
3 | testcase-data { | ||
4 | platform-tests { | ||
5 | #address-cells = <1>; | ||
6 | #size-cells = <0>; | ||
7 | |||
8 | test-device@0 { | ||
9 | compatible = "test-device"; | ||
10 | reg = <0x0>; | ||
11 | |||
12 | #address-cells = <1>; | ||
13 | #size-cells = <0>; | ||
14 | |||
15 | dev@100 { | ||
16 | compatible = "test-sub-device"; | ||
17 | reg = <0x100>; | ||
18 | }; | ||
19 | }; | ||
20 | |||
21 | test-device@1 { | ||
22 | compatible = "test-device"; | ||
23 | reg = <0x1>; | ||
24 | |||
25 | #address-cells = <1>; | ||
26 | #size-cells = <0>; | ||
27 | |||
28 | dev@100 { | ||
29 | compatible = "test-sub-device"; | ||
30 | reg = <0x100>; | ||
31 | }; | ||
32 | }; | ||
33 | }; | ||
34 | }; | ||
35 | }; | ||