diff options
author | Stephen Neuendorffer <stephen.neuendorffer@xilinx.com> | 2010-11-18 18:54:59 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-12-29 18:53:45 -0500 |
commit | 9706a36e35c4ce04f28a62cfe1205b4e3b0dd13c (patch) | |
tree | 12f378664e5fa9fe560b281fa56214772df3f6ab /drivers/of | |
parent | e6ce1324e4f08b0d984340201a125806dae0e9a6 (diff) |
of/flattree: Add non-boottime device tree functions
In preparation for providing run-time handling of device trees, factor
out some of the basic functions so that they take an arbitrary blob,
rather than relying on the single boot-time tree.
V2:
- functions have of_fdt_* names
- removed find_flat_dt_string
- blob argument is first
Signed-off-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/fdt.c | 133 |
1 files changed, 79 insertions, 54 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 2ebacf14e7de..10eab21076ea 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -22,6 +22,82 @@ | |||
22 | 22 | ||
23 | #include <asm/page.h> | 23 | #include <asm/page.h> |
24 | 24 | ||
25 | char *of_fdt_get_string(struct boot_param_header *blob, u32 offset) | ||
26 | { | ||
27 | return ((char *)blob) + | ||
28 | be32_to_cpu(blob->off_dt_strings) + offset; | ||
29 | } | ||
30 | |||
31 | /** | ||
32 | * of_fdt_get_property - Given a node in the given flat blob, return | ||
33 | * the property ptr | ||
34 | */ | ||
35 | void *of_fdt_get_property(struct boot_param_header *blob, | ||
36 | unsigned long node, const char *name, | ||
37 | unsigned long *size) | ||
38 | { | ||
39 | unsigned long p = node; | ||
40 | |||
41 | do { | ||
42 | u32 tag = be32_to_cpup((__be32 *)p); | ||
43 | u32 sz, noff; | ||
44 | const char *nstr; | ||
45 | |||
46 | p += 4; | ||
47 | if (tag == OF_DT_NOP) | ||
48 | continue; | ||
49 | if (tag != OF_DT_PROP) | ||
50 | return NULL; | ||
51 | |||
52 | sz = be32_to_cpup((__be32 *)p); | ||
53 | noff = be32_to_cpup((__be32 *)(p + 4)); | ||
54 | p += 8; | ||
55 | if (be32_to_cpu(blob->version) < 0x10) | ||
56 | p = ALIGN(p, sz >= 8 ? 8 : 4); | ||
57 | |||
58 | nstr = of_fdt_get_string(blob, noff); | ||
59 | if (nstr == NULL) { | ||
60 | pr_warning("Can't find property index name !\n"); | ||
61 | return NULL; | ||
62 | } | ||
63 | if (strcmp(name, nstr) == 0) { | ||
64 | if (size) | ||
65 | *size = sz; | ||
66 | return (void *)p; | ||
67 | } | ||
68 | p += sz; | ||
69 | p = ALIGN(p, 4); | ||
70 | } while (1); | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * of_fdt_is_compatible - Return true if given node from the given blob has | ||
75 | * compat in its compatible list | ||
76 | * @blob: A device tree blob | ||
77 | * @node: node to test | ||
78 | * @compat: compatible string to compare with compatible list. | ||
79 | */ | ||
80 | int of_fdt_is_compatible(struct boot_param_header *blob, | ||
81 | unsigned long node, const char *compat) | ||
82 | { | ||
83 | const char *cp; | ||
84 | unsigned long cplen, l; | ||
85 | |||
86 | cp = of_fdt_get_property(blob, node, "compatible", &cplen); | ||
87 | if (cp == NULL) | ||
88 | return 0; | ||
89 | while (cplen > 0) { | ||
90 | if (of_compat_cmp(cp, compat, strlen(compat)) == 0) | ||
91 | return 1; | ||
92 | l = strlen(cp) + 1; | ||
93 | cp += l; | ||
94 | cplen -= l; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | /* Everything below here references initial_boot_params directly. */ | ||
25 | int __initdata dt_root_addr_cells; | 101 | int __initdata dt_root_addr_cells; |
26 | int __initdata dt_root_size_cells; | 102 | int __initdata dt_root_size_cells; |
27 | 103 | ||
@@ -29,12 +105,6 @@ struct boot_param_header *initial_boot_params; | |||
29 | 105 | ||
30 | #ifdef CONFIG_OF_EARLY_FLATTREE | 106 | #ifdef CONFIG_OF_EARLY_FLATTREE |
31 | 107 | ||
32 | char *find_flat_dt_string(u32 offset) | ||
33 | { | ||
34 | return ((char *)initial_boot_params) + | ||
35 | be32_to_cpu(initial_boot_params->off_dt_strings) + offset; | ||
36 | } | ||
37 | |||
38 | /** | 108 | /** |
39 | * of_scan_flat_dt - scan flattened tree blob and call callback on each. | 109 | * of_scan_flat_dt - scan flattened tree blob and call callback on each. |
40 | * @it: callback function | 110 | * @it: callback function |
@@ -123,38 +193,7 @@ unsigned long __init of_get_flat_dt_root(void) | |||
123 | void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | 193 | void *__init of_get_flat_dt_prop(unsigned long node, const char *name, |
124 | unsigned long *size) | 194 | unsigned long *size) |
125 | { | 195 | { |
126 | unsigned long p = node; | 196 | return of_fdt_get_property(initial_boot_params, node, name, size); |
127 | |||
128 | do { | ||
129 | u32 tag = be32_to_cpup((__be32 *)p); | ||
130 | u32 sz, noff; | ||
131 | const char *nstr; | ||
132 | |||
133 | p += 4; | ||
134 | if (tag == OF_DT_NOP) | ||
135 | continue; | ||
136 | if (tag != OF_DT_PROP) | ||
137 | return NULL; | ||
138 | |||
139 | sz = be32_to_cpup((__be32 *)p); | ||
140 | noff = be32_to_cpup((__be32 *)(p + 4)); | ||
141 | p += 8; | ||
142 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | ||
143 | p = ALIGN(p, sz >= 8 ? 8 : 4); | ||
144 | |||
145 | nstr = find_flat_dt_string(noff); | ||
146 | if (nstr == NULL) { | ||
147 | pr_warning("Can't find property index name !\n"); | ||
148 | return NULL; | ||
149 | } | ||
150 | if (strcmp(name, nstr) == 0) { | ||
151 | if (size) | ||
152 | *size = sz; | ||
153 | return (void *)p; | ||
154 | } | ||
155 | p += sz; | ||
156 | p = ALIGN(p, 4); | ||
157 | } while (1); | ||
158 | } | 197 | } |
159 | 198 | ||
160 | /** | 199 | /** |
@@ -164,21 +203,7 @@ void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | |||
164 | */ | 203 | */ |
165 | int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) | 204 | int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) |
166 | { | 205 | { |
167 | const char *cp; | 206 | return of_fdt_is_compatible(initial_boot_params, node, compat); |
168 | unsigned long cplen, l; | ||
169 | |||
170 | cp = of_get_flat_dt_prop(node, "compatible", &cplen); | ||
171 | if (cp == NULL) | ||
172 | return 0; | ||
173 | while (cplen > 0) { | ||
174 | if (of_compat_cmp(cp, compat, strlen(compat)) == 0) | ||
175 | return 1; | ||
176 | l = strlen(cp) + 1; | ||
177 | cp += l; | ||
178 | cplen -= l; | ||
179 | } | ||
180 | |||
181 | return 0; | ||
182 | } | 207 | } |
183 | 208 | ||
184 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, | 209 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, |
@@ -303,7 +328,7 @@ unsigned long __init unflatten_dt_node(unsigned long mem, | |||
303 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | 328 | if (be32_to_cpu(initial_boot_params->version) < 0x10) |
304 | *p = ALIGN(*p, sz >= 8 ? 8 : 4); | 329 | *p = ALIGN(*p, sz >= 8 ? 8 : 4); |
305 | 330 | ||
306 | pname = find_flat_dt_string(noff); | 331 | pname = of_fdt_get_string(initial_boot_params, noff); |
307 | if (pname == NULL) { | 332 | if (pname == NULL) { |
308 | pr_info("Can't find property name in list !\n"); | 333 | pr_info("Can't find property name in list !\n"); |
309 | break; | 334 | break; |