Commit 49b97d9c8ea7b11c4fc9e457cc2cd9fd6ebf0c21
1 parent
69bcf5bc80
Exists in
master
and in
56 other branches
fdt: Add fdt_del_node_and_alias helper
Add a helper function that given an alias will delete both the node the alias points to and the alias itself Signed-off-by: Kumar Gala <galak@kernel.crashing.org> Acked-by: Gerald Van Baren <vanbaren@cideas.com>
Showing 2 changed files with 14 additions and 0 deletions Inline Diff
common/fdt_support.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2007 | 2 | * (C) Copyright 2007 |
3 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com | 3 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com |
4 | * | 4 | * |
5 | * See file CREDITS for list of people who contributed to this | 5 | * See file CREDITS for list of people who contributed to this |
6 | * project. | 6 | * project. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License as | 9 | * modify it under the terms of the GNU General Public License as |
10 | * published by the Free Software Foundation; either version 2 of | 10 | * published by the Free Software Foundation; either version 2 of |
11 | * the License, or (at your option) any later version. | 11 | * the License, or (at your option) any later version. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
21 | * MA 02111-1307 USA | 21 | * MA 02111-1307 USA |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <common.h> | 24 | #include <common.h> |
25 | #include <stdio_dev.h> | 25 | #include <stdio_dev.h> |
26 | #include <linux/ctype.h> | 26 | #include <linux/ctype.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <asm/global_data.h> | 28 | #include <asm/global_data.h> |
29 | #include <fdt.h> | 29 | #include <fdt.h> |
30 | #include <libfdt.h> | 30 | #include <libfdt.h> |
31 | #include <fdt_support.h> | 31 | #include <fdt_support.h> |
32 | #include <exports.h> | 32 | #include <exports.h> |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * Global data (for the gd->bd) | 35 | * Global data (for the gd->bd) |
36 | */ | 36 | */ |
37 | DECLARE_GLOBAL_DATA_PTR; | 37 | DECLARE_GLOBAL_DATA_PTR; |
38 | 38 | ||
39 | /** | 39 | /** |
40 | * fdt_getprop_u32_default - Find a node and return it's property or a default | 40 | * fdt_getprop_u32_default - Find a node and return it's property or a default |
41 | * | 41 | * |
42 | * @fdt: ptr to device tree | 42 | * @fdt: ptr to device tree |
43 | * @path: path of node | 43 | * @path: path of node |
44 | * @prop: property name | 44 | * @prop: property name |
45 | * @dflt: default value if the property isn't found | 45 | * @dflt: default value if the property isn't found |
46 | * | 46 | * |
47 | * Convenience function to find a node and return it's property or a | 47 | * Convenience function to find a node and return it's property or a |
48 | * default value if it doesn't exist. | 48 | * default value if it doesn't exist. |
49 | */ | 49 | */ |
50 | u32 fdt_getprop_u32_default(void *fdt, const char *path, const char *prop, | 50 | u32 fdt_getprop_u32_default(void *fdt, const char *path, const char *prop, |
51 | const u32 dflt) | 51 | const u32 dflt) |
52 | { | 52 | { |
53 | const u32 *val; | 53 | const u32 *val; |
54 | int off; | 54 | int off; |
55 | 55 | ||
56 | off = fdt_path_offset(fdt, path); | 56 | off = fdt_path_offset(fdt, path); |
57 | if (off < 0) | 57 | if (off < 0) |
58 | return dflt; | 58 | return dflt; |
59 | 59 | ||
60 | val = fdt_getprop(fdt, off, prop, NULL); | 60 | val = fdt_getprop(fdt, off, prop, NULL); |
61 | if (val) | 61 | if (val) |
62 | return *val; | 62 | return *val; |
63 | else | 63 | else |
64 | return dflt; | 64 | return dflt; |
65 | } | 65 | } |
66 | 66 | ||
67 | /** | 67 | /** |
68 | * fdt_find_and_setprop: Find a node and set it's property | 68 | * fdt_find_and_setprop: Find a node and set it's property |
69 | * | 69 | * |
70 | * @fdt: ptr to device tree | 70 | * @fdt: ptr to device tree |
71 | * @node: path of node | 71 | * @node: path of node |
72 | * @prop: property name | 72 | * @prop: property name |
73 | * @val: ptr to new value | 73 | * @val: ptr to new value |
74 | * @len: length of new property value | 74 | * @len: length of new property value |
75 | * @create: flag to create the property if it doesn't exist | 75 | * @create: flag to create the property if it doesn't exist |
76 | * | 76 | * |
77 | * Convenience function to directly set a property given the path to the node. | 77 | * Convenience function to directly set a property given the path to the node. |
78 | */ | 78 | */ |
79 | int fdt_find_and_setprop(void *fdt, const char *node, const char *prop, | 79 | int fdt_find_and_setprop(void *fdt, const char *node, const char *prop, |
80 | const void *val, int len, int create) | 80 | const void *val, int len, int create) |
81 | { | 81 | { |
82 | int nodeoff = fdt_path_offset(fdt, node); | 82 | int nodeoff = fdt_path_offset(fdt, node); |
83 | 83 | ||
84 | if (nodeoff < 0) | 84 | if (nodeoff < 0) |
85 | return nodeoff; | 85 | return nodeoff; |
86 | 86 | ||
87 | if ((!create) && (fdt_get_property(fdt, nodeoff, prop, 0) == NULL)) | 87 | if ((!create) && (fdt_get_property(fdt, nodeoff, prop, 0) == NULL)) |
88 | return 0; /* create flag not set; so exit quietly */ | 88 | return 0; /* create flag not set; so exit quietly */ |
89 | 89 | ||
90 | return fdt_setprop(fdt, nodeoff, prop, val, len); | 90 | return fdt_setprop(fdt, nodeoff, prop, val, len); |
91 | } | 91 | } |
92 | 92 | ||
93 | #ifdef CONFIG_OF_STDOUT_VIA_ALIAS | 93 | #ifdef CONFIG_OF_STDOUT_VIA_ALIAS |
94 | 94 | ||
95 | #ifdef CONFIG_SERIAL_MULTI | 95 | #ifdef CONFIG_SERIAL_MULTI |
96 | static void fdt_fill_multisername(char *sername, size_t maxlen) | 96 | static void fdt_fill_multisername(char *sername, size_t maxlen) |
97 | { | 97 | { |
98 | const char *outname = stdio_devices[stdout]->name; | 98 | const char *outname = stdio_devices[stdout]->name; |
99 | 99 | ||
100 | if (strcmp(outname, "serial") > 0) | 100 | if (strcmp(outname, "serial") > 0) |
101 | strncpy(sername, outname, maxlen); | 101 | strncpy(sername, outname, maxlen); |
102 | 102 | ||
103 | /* eserial? */ | 103 | /* eserial? */ |
104 | if (strcmp(outname + 1, "serial") > 0) | 104 | if (strcmp(outname + 1, "serial") > 0) |
105 | strncpy(sername, outname + 1, maxlen); | 105 | strncpy(sername, outname + 1, maxlen); |
106 | } | 106 | } |
107 | #else | 107 | #else |
108 | static inline void fdt_fill_multisername(char *sername, size_t maxlen) {} | 108 | static inline void fdt_fill_multisername(char *sername, size_t maxlen) {} |
109 | #endif /* CONFIG_SERIAL_MULTI */ | 109 | #endif /* CONFIG_SERIAL_MULTI */ |
110 | 110 | ||
111 | static int fdt_fixup_stdout(void *fdt, int chosenoff) | 111 | static int fdt_fixup_stdout(void *fdt, int chosenoff) |
112 | { | 112 | { |
113 | int err = 0; | 113 | int err = 0; |
114 | #ifdef CONFIG_CONS_INDEX | 114 | #ifdef CONFIG_CONS_INDEX |
115 | int node; | 115 | int node; |
116 | char sername[9] = { 0 }; | 116 | char sername[9] = { 0 }; |
117 | const char *path; | 117 | const char *path; |
118 | 118 | ||
119 | fdt_fill_multisername(sername, sizeof(sername) - 1); | 119 | fdt_fill_multisername(sername, sizeof(sername) - 1); |
120 | if (!sername[0]) | 120 | if (!sername[0]) |
121 | sprintf(sername, "serial%d", CONFIG_CONS_INDEX - 1); | 121 | sprintf(sername, "serial%d", CONFIG_CONS_INDEX - 1); |
122 | 122 | ||
123 | err = node = fdt_path_offset(fdt, "/aliases"); | 123 | err = node = fdt_path_offset(fdt, "/aliases"); |
124 | if (node >= 0) { | 124 | if (node >= 0) { |
125 | int len; | 125 | int len; |
126 | path = fdt_getprop(fdt, node, sername, &len); | 126 | path = fdt_getprop(fdt, node, sername, &len); |
127 | if (path) { | 127 | if (path) { |
128 | char *p = malloc(len); | 128 | char *p = malloc(len); |
129 | err = -FDT_ERR_NOSPACE; | 129 | err = -FDT_ERR_NOSPACE; |
130 | if (p) { | 130 | if (p) { |
131 | memcpy(p, path, len); | 131 | memcpy(p, path, len); |
132 | err = fdt_setprop(fdt, chosenoff, | 132 | err = fdt_setprop(fdt, chosenoff, |
133 | "linux,stdout-path", p, len); | 133 | "linux,stdout-path", p, len); |
134 | free(p); | 134 | free(p); |
135 | } | 135 | } |
136 | } else { | 136 | } else { |
137 | err = len; | 137 | err = len; |
138 | } | 138 | } |
139 | } | 139 | } |
140 | #endif | 140 | #endif |
141 | if (err < 0) | 141 | if (err < 0) |
142 | printf("WARNING: could not set linux,stdout-path %s.\n", | 142 | printf("WARNING: could not set linux,stdout-path %s.\n", |
143 | fdt_strerror(err)); | 143 | fdt_strerror(err)); |
144 | 144 | ||
145 | return err; | 145 | return err; |
146 | } | 146 | } |
147 | #endif | 147 | #endif |
148 | 148 | ||
149 | int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force) | 149 | int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force) |
150 | { | 150 | { |
151 | int nodeoffset; | 151 | int nodeoffset; |
152 | int err, j, total; | 152 | int err, j, total; |
153 | u32 tmp; | 153 | u32 tmp; |
154 | const char *path; | 154 | const char *path; |
155 | uint64_t addr, size; | 155 | uint64_t addr, size; |
156 | 156 | ||
157 | /* Find the "chosen" node. */ | 157 | /* Find the "chosen" node. */ |
158 | nodeoffset = fdt_path_offset (fdt, "/chosen"); | 158 | nodeoffset = fdt_path_offset (fdt, "/chosen"); |
159 | 159 | ||
160 | /* If there is no "chosen" node in the blob return */ | 160 | /* If there is no "chosen" node in the blob return */ |
161 | if (nodeoffset < 0) { | 161 | if (nodeoffset < 0) { |
162 | printf("fdt_initrd: %s\n", fdt_strerror(nodeoffset)); | 162 | printf("fdt_initrd: %s\n", fdt_strerror(nodeoffset)); |
163 | return nodeoffset; | 163 | return nodeoffset; |
164 | } | 164 | } |
165 | 165 | ||
166 | /* just return if initrd_start/end aren't valid */ | 166 | /* just return if initrd_start/end aren't valid */ |
167 | if ((initrd_start == 0) || (initrd_end == 0)) | 167 | if ((initrd_start == 0) || (initrd_end == 0)) |
168 | return 0; | 168 | return 0; |
169 | 169 | ||
170 | total = fdt_num_mem_rsv(fdt); | 170 | total = fdt_num_mem_rsv(fdt); |
171 | 171 | ||
172 | /* | 172 | /* |
173 | * Look for an existing entry and update it. If we don't find | 173 | * Look for an existing entry and update it. If we don't find |
174 | * the entry, we will j be the next available slot. | 174 | * the entry, we will j be the next available slot. |
175 | */ | 175 | */ |
176 | for (j = 0; j < total; j++) { | 176 | for (j = 0; j < total; j++) { |
177 | err = fdt_get_mem_rsv(fdt, j, &addr, &size); | 177 | err = fdt_get_mem_rsv(fdt, j, &addr, &size); |
178 | if (addr == initrd_start) { | 178 | if (addr == initrd_start) { |
179 | fdt_del_mem_rsv(fdt, j); | 179 | fdt_del_mem_rsv(fdt, j); |
180 | break; | 180 | break; |
181 | } | 181 | } |
182 | } | 182 | } |
183 | 183 | ||
184 | err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start + 1); | 184 | err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start + 1); |
185 | if (err < 0) { | 185 | if (err < 0) { |
186 | printf("fdt_initrd: %s\n", fdt_strerror(err)); | 186 | printf("fdt_initrd: %s\n", fdt_strerror(err)); |
187 | return err; | 187 | return err; |
188 | } | 188 | } |
189 | 189 | ||
190 | path = fdt_getprop(fdt, nodeoffset, "linux,initrd-start", NULL); | 190 | path = fdt_getprop(fdt, nodeoffset, "linux,initrd-start", NULL); |
191 | if ((path == NULL) || force) { | 191 | if ((path == NULL) || force) { |
192 | tmp = __cpu_to_be32(initrd_start); | 192 | tmp = __cpu_to_be32(initrd_start); |
193 | err = fdt_setprop(fdt, nodeoffset, | 193 | err = fdt_setprop(fdt, nodeoffset, |
194 | "linux,initrd-start", &tmp, sizeof(tmp)); | 194 | "linux,initrd-start", &tmp, sizeof(tmp)); |
195 | if (err < 0) { | 195 | if (err < 0) { |
196 | printf("WARNING: " | 196 | printf("WARNING: " |
197 | "could not set linux,initrd-start %s.\n", | 197 | "could not set linux,initrd-start %s.\n", |
198 | fdt_strerror(err)); | 198 | fdt_strerror(err)); |
199 | return err; | 199 | return err; |
200 | } | 200 | } |
201 | tmp = __cpu_to_be32(initrd_end); | 201 | tmp = __cpu_to_be32(initrd_end); |
202 | err = fdt_setprop(fdt, nodeoffset, | 202 | err = fdt_setprop(fdt, nodeoffset, |
203 | "linux,initrd-end", &tmp, sizeof(tmp)); | 203 | "linux,initrd-end", &tmp, sizeof(tmp)); |
204 | if (err < 0) { | 204 | if (err < 0) { |
205 | printf("WARNING: could not set linux,initrd-end %s.\n", | 205 | printf("WARNING: could not set linux,initrd-end %s.\n", |
206 | fdt_strerror(err)); | 206 | fdt_strerror(err)); |
207 | 207 | ||
208 | return err; | 208 | return err; |
209 | } | 209 | } |
210 | } | 210 | } |
211 | 211 | ||
212 | return 0; | 212 | return 0; |
213 | } | 213 | } |
214 | 214 | ||
215 | int fdt_chosen(void *fdt, int force) | 215 | int fdt_chosen(void *fdt, int force) |
216 | { | 216 | { |
217 | int nodeoffset; | 217 | int nodeoffset; |
218 | int err; | 218 | int err; |
219 | char *str; /* used to set string properties */ | 219 | char *str; /* used to set string properties */ |
220 | const char *path; | 220 | const char *path; |
221 | 221 | ||
222 | err = fdt_check_header(fdt); | 222 | err = fdt_check_header(fdt); |
223 | if (err < 0) { | 223 | if (err < 0) { |
224 | printf("fdt_chosen: %s\n", fdt_strerror(err)); | 224 | printf("fdt_chosen: %s\n", fdt_strerror(err)); |
225 | return err; | 225 | return err; |
226 | } | 226 | } |
227 | 227 | ||
228 | /* | 228 | /* |
229 | * Find the "chosen" node. | 229 | * Find the "chosen" node. |
230 | */ | 230 | */ |
231 | nodeoffset = fdt_path_offset (fdt, "/chosen"); | 231 | nodeoffset = fdt_path_offset (fdt, "/chosen"); |
232 | 232 | ||
233 | /* | 233 | /* |
234 | * If there is no "chosen" node in the blob, create it. | 234 | * If there is no "chosen" node in the blob, create it. |
235 | */ | 235 | */ |
236 | if (nodeoffset < 0) { | 236 | if (nodeoffset < 0) { |
237 | /* | 237 | /* |
238 | * Create a new node "/chosen" (offset 0 is root level) | 238 | * Create a new node "/chosen" (offset 0 is root level) |
239 | */ | 239 | */ |
240 | nodeoffset = fdt_add_subnode(fdt, 0, "chosen"); | 240 | nodeoffset = fdt_add_subnode(fdt, 0, "chosen"); |
241 | if (nodeoffset < 0) { | 241 | if (nodeoffset < 0) { |
242 | printf("WARNING: could not create /chosen %s.\n", | 242 | printf("WARNING: could not create /chosen %s.\n", |
243 | fdt_strerror(nodeoffset)); | 243 | fdt_strerror(nodeoffset)); |
244 | return nodeoffset; | 244 | return nodeoffset; |
245 | } | 245 | } |
246 | } | 246 | } |
247 | 247 | ||
248 | /* | 248 | /* |
249 | * Create /chosen properites that don't exist in the fdt. | 249 | * Create /chosen properites that don't exist in the fdt. |
250 | * If the property exists, update it only if the "force" parameter | 250 | * If the property exists, update it only if the "force" parameter |
251 | * is true. | 251 | * is true. |
252 | */ | 252 | */ |
253 | str = getenv("bootargs"); | 253 | str = getenv("bootargs"); |
254 | if (str != NULL) { | 254 | if (str != NULL) { |
255 | path = fdt_getprop(fdt, nodeoffset, "bootargs", NULL); | 255 | path = fdt_getprop(fdt, nodeoffset, "bootargs", NULL); |
256 | if ((path == NULL) || force) { | 256 | if ((path == NULL) || force) { |
257 | err = fdt_setprop(fdt, nodeoffset, | 257 | err = fdt_setprop(fdt, nodeoffset, |
258 | "bootargs", str, strlen(str)+1); | 258 | "bootargs", str, strlen(str)+1); |
259 | if (err < 0) | 259 | if (err < 0) |
260 | printf("WARNING: could not set bootargs %s.\n", | 260 | printf("WARNING: could not set bootargs %s.\n", |
261 | fdt_strerror(err)); | 261 | fdt_strerror(err)); |
262 | } | 262 | } |
263 | } | 263 | } |
264 | 264 | ||
265 | #ifdef CONFIG_OF_STDOUT_VIA_ALIAS | 265 | #ifdef CONFIG_OF_STDOUT_VIA_ALIAS |
266 | path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL); | 266 | path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL); |
267 | if ((path == NULL) || force) | 267 | if ((path == NULL) || force) |
268 | err = fdt_fixup_stdout(fdt, nodeoffset); | 268 | err = fdt_fixup_stdout(fdt, nodeoffset); |
269 | #endif | 269 | #endif |
270 | 270 | ||
271 | #ifdef OF_STDOUT_PATH | 271 | #ifdef OF_STDOUT_PATH |
272 | path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL); | 272 | path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL); |
273 | if ((path == NULL) || force) { | 273 | if ((path == NULL) || force) { |
274 | err = fdt_setprop(fdt, nodeoffset, | 274 | err = fdt_setprop(fdt, nodeoffset, |
275 | "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1); | 275 | "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1); |
276 | if (err < 0) | 276 | if (err < 0) |
277 | printf("WARNING: could not set linux,stdout-path %s.\n", | 277 | printf("WARNING: could not set linux,stdout-path %s.\n", |
278 | fdt_strerror(err)); | 278 | fdt_strerror(err)); |
279 | } | 279 | } |
280 | #endif | 280 | #endif |
281 | 281 | ||
282 | return err; | 282 | return err; |
283 | } | 283 | } |
284 | 284 | ||
285 | void do_fixup_by_path(void *fdt, const char *path, const char *prop, | 285 | void do_fixup_by_path(void *fdt, const char *path, const char *prop, |
286 | const void *val, int len, int create) | 286 | const void *val, int len, int create) |
287 | { | 287 | { |
288 | #if defined(DEBUG) | 288 | #if defined(DEBUG) |
289 | int i; | 289 | int i; |
290 | debug("Updating property '%s/%s' = ", path, prop); | 290 | debug("Updating property '%s/%s' = ", path, prop); |
291 | for (i = 0; i < len; i++) | 291 | for (i = 0; i < len; i++) |
292 | debug(" %.2x", *(u8*)(val+i)); | 292 | debug(" %.2x", *(u8*)(val+i)); |
293 | debug("\n"); | 293 | debug("\n"); |
294 | #endif | 294 | #endif |
295 | int rc = fdt_find_and_setprop(fdt, path, prop, val, len, create); | 295 | int rc = fdt_find_and_setprop(fdt, path, prop, val, len, create); |
296 | if (rc) | 296 | if (rc) |
297 | printf("Unable to update property %s:%s, err=%s\n", | 297 | printf("Unable to update property %s:%s, err=%s\n", |
298 | path, prop, fdt_strerror(rc)); | 298 | path, prop, fdt_strerror(rc)); |
299 | } | 299 | } |
300 | 300 | ||
301 | void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop, | 301 | void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop, |
302 | u32 val, int create) | 302 | u32 val, int create) |
303 | { | 303 | { |
304 | val = cpu_to_fdt32(val); | 304 | val = cpu_to_fdt32(val); |
305 | do_fixup_by_path(fdt, path, prop, &val, sizeof(val), create); | 305 | do_fixup_by_path(fdt, path, prop, &val, sizeof(val), create); |
306 | } | 306 | } |
307 | 307 | ||
308 | void do_fixup_by_prop(void *fdt, | 308 | void do_fixup_by_prop(void *fdt, |
309 | const char *pname, const void *pval, int plen, | 309 | const char *pname, const void *pval, int plen, |
310 | const char *prop, const void *val, int len, | 310 | const char *prop, const void *val, int len, |
311 | int create) | 311 | int create) |
312 | { | 312 | { |
313 | int off; | 313 | int off; |
314 | #if defined(DEBUG) | 314 | #if defined(DEBUG) |
315 | int i; | 315 | int i; |
316 | debug("Updating property '%s' = ", prop); | 316 | debug("Updating property '%s' = ", prop); |
317 | for (i = 0; i < len; i++) | 317 | for (i = 0; i < len; i++) |
318 | debug(" %.2x", *(u8*)(val+i)); | 318 | debug(" %.2x", *(u8*)(val+i)); |
319 | debug("\n"); | 319 | debug("\n"); |
320 | #endif | 320 | #endif |
321 | off = fdt_node_offset_by_prop_value(fdt, -1, pname, pval, plen); | 321 | off = fdt_node_offset_by_prop_value(fdt, -1, pname, pval, plen); |
322 | while (off != -FDT_ERR_NOTFOUND) { | 322 | while (off != -FDT_ERR_NOTFOUND) { |
323 | if (create || (fdt_get_property(fdt, off, prop, 0) != NULL)) | 323 | if (create || (fdt_get_property(fdt, off, prop, 0) != NULL)) |
324 | fdt_setprop(fdt, off, prop, val, len); | 324 | fdt_setprop(fdt, off, prop, val, len); |
325 | off = fdt_node_offset_by_prop_value(fdt, off, pname, pval, plen); | 325 | off = fdt_node_offset_by_prop_value(fdt, off, pname, pval, plen); |
326 | } | 326 | } |
327 | } | 327 | } |
328 | 328 | ||
329 | void do_fixup_by_prop_u32(void *fdt, | 329 | void do_fixup_by_prop_u32(void *fdt, |
330 | const char *pname, const void *pval, int plen, | 330 | const char *pname, const void *pval, int plen, |
331 | const char *prop, u32 val, int create) | 331 | const char *prop, u32 val, int create) |
332 | { | 332 | { |
333 | val = cpu_to_fdt32(val); | 333 | val = cpu_to_fdt32(val); |
334 | do_fixup_by_prop(fdt, pname, pval, plen, prop, &val, 4, create); | 334 | do_fixup_by_prop(fdt, pname, pval, plen, prop, &val, 4, create); |
335 | } | 335 | } |
336 | 336 | ||
337 | void do_fixup_by_compat(void *fdt, const char *compat, | 337 | void do_fixup_by_compat(void *fdt, const char *compat, |
338 | const char *prop, const void *val, int len, int create) | 338 | const char *prop, const void *val, int len, int create) |
339 | { | 339 | { |
340 | int off = -1; | 340 | int off = -1; |
341 | #if defined(DEBUG) | 341 | #if defined(DEBUG) |
342 | int i; | 342 | int i; |
343 | debug("Updating property '%s' = ", prop); | 343 | debug("Updating property '%s' = ", prop); |
344 | for (i = 0; i < len; i++) | 344 | for (i = 0; i < len; i++) |
345 | debug(" %.2x", *(u8*)(val+i)); | 345 | debug(" %.2x", *(u8*)(val+i)); |
346 | debug("\n"); | 346 | debug("\n"); |
347 | #endif | 347 | #endif |
348 | off = fdt_node_offset_by_compatible(fdt, -1, compat); | 348 | off = fdt_node_offset_by_compatible(fdt, -1, compat); |
349 | while (off != -FDT_ERR_NOTFOUND) { | 349 | while (off != -FDT_ERR_NOTFOUND) { |
350 | if (create || (fdt_get_property(fdt, off, prop, 0) != NULL)) | 350 | if (create || (fdt_get_property(fdt, off, prop, 0) != NULL)) |
351 | fdt_setprop(fdt, off, prop, val, len); | 351 | fdt_setprop(fdt, off, prop, val, len); |
352 | off = fdt_node_offset_by_compatible(fdt, off, compat); | 352 | off = fdt_node_offset_by_compatible(fdt, off, compat); |
353 | } | 353 | } |
354 | } | 354 | } |
355 | 355 | ||
356 | void do_fixup_by_compat_u32(void *fdt, const char *compat, | 356 | void do_fixup_by_compat_u32(void *fdt, const char *compat, |
357 | const char *prop, u32 val, int create) | 357 | const char *prop, u32 val, int create) |
358 | { | 358 | { |
359 | val = cpu_to_fdt32(val); | 359 | val = cpu_to_fdt32(val); |
360 | do_fixup_by_compat(fdt, compat, prop, &val, 4, create); | 360 | do_fixup_by_compat(fdt, compat, prop, &val, 4, create); |
361 | } | 361 | } |
362 | 362 | ||
363 | int fdt_fixup_memory(void *blob, u64 start, u64 size) | 363 | int fdt_fixup_memory(void *blob, u64 start, u64 size) |
364 | { | 364 | { |
365 | int err, nodeoffset, len = 0; | 365 | int err, nodeoffset, len = 0; |
366 | u8 tmp[16]; | 366 | u8 tmp[16]; |
367 | const u32 *addrcell, *sizecell; | 367 | const u32 *addrcell, *sizecell; |
368 | 368 | ||
369 | err = fdt_check_header(blob); | 369 | err = fdt_check_header(blob); |
370 | if (err < 0) { | 370 | if (err < 0) { |
371 | printf("%s: %s\n", __FUNCTION__, fdt_strerror(err)); | 371 | printf("%s: %s\n", __FUNCTION__, fdt_strerror(err)); |
372 | return err; | 372 | return err; |
373 | } | 373 | } |
374 | 374 | ||
375 | /* update, or add and update /memory node */ | 375 | /* update, or add and update /memory node */ |
376 | nodeoffset = fdt_path_offset(blob, "/memory"); | 376 | nodeoffset = fdt_path_offset(blob, "/memory"); |
377 | if (nodeoffset < 0) { | 377 | if (nodeoffset < 0) { |
378 | nodeoffset = fdt_add_subnode(blob, 0, "memory"); | 378 | nodeoffset = fdt_add_subnode(blob, 0, "memory"); |
379 | if (nodeoffset < 0) | 379 | if (nodeoffset < 0) |
380 | printf("WARNING: could not create /memory: %s.\n", | 380 | printf("WARNING: could not create /memory: %s.\n", |
381 | fdt_strerror(nodeoffset)); | 381 | fdt_strerror(nodeoffset)); |
382 | return nodeoffset; | 382 | return nodeoffset; |
383 | } | 383 | } |
384 | err = fdt_setprop(blob, nodeoffset, "device_type", "memory", | 384 | err = fdt_setprop(blob, nodeoffset, "device_type", "memory", |
385 | sizeof("memory")); | 385 | sizeof("memory")); |
386 | if (err < 0) { | 386 | if (err < 0) { |
387 | printf("WARNING: could not set %s %s.\n", "device_type", | 387 | printf("WARNING: could not set %s %s.\n", "device_type", |
388 | fdt_strerror(err)); | 388 | fdt_strerror(err)); |
389 | return err; | 389 | return err; |
390 | } | 390 | } |
391 | 391 | ||
392 | addrcell = fdt_getprop(blob, 0, "#address-cells", NULL); | 392 | addrcell = fdt_getprop(blob, 0, "#address-cells", NULL); |
393 | /* use shifts and mask to ensure endianness */ | 393 | /* use shifts and mask to ensure endianness */ |
394 | if ((addrcell) && (*addrcell == 2)) { | 394 | if ((addrcell) && (*addrcell == 2)) { |
395 | tmp[0] = (start >> 56) & 0xff; | 395 | tmp[0] = (start >> 56) & 0xff; |
396 | tmp[1] = (start >> 48) & 0xff; | 396 | tmp[1] = (start >> 48) & 0xff; |
397 | tmp[2] = (start >> 40) & 0xff; | 397 | tmp[2] = (start >> 40) & 0xff; |
398 | tmp[3] = (start >> 32) & 0xff; | 398 | tmp[3] = (start >> 32) & 0xff; |
399 | tmp[4] = (start >> 24) & 0xff; | 399 | tmp[4] = (start >> 24) & 0xff; |
400 | tmp[5] = (start >> 16) & 0xff; | 400 | tmp[5] = (start >> 16) & 0xff; |
401 | tmp[6] = (start >> 8) & 0xff; | 401 | tmp[6] = (start >> 8) & 0xff; |
402 | tmp[7] = (start ) & 0xff; | 402 | tmp[7] = (start ) & 0xff; |
403 | len = 8; | 403 | len = 8; |
404 | } else { | 404 | } else { |
405 | tmp[0] = (start >> 24) & 0xff; | 405 | tmp[0] = (start >> 24) & 0xff; |
406 | tmp[1] = (start >> 16) & 0xff; | 406 | tmp[1] = (start >> 16) & 0xff; |
407 | tmp[2] = (start >> 8) & 0xff; | 407 | tmp[2] = (start >> 8) & 0xff; |
408 | tmp[3] = (start ) & 0xff; | 408 | tmp[3] = (start ) & 0xff; |
409 | len = 4; | 409 | len = 4; |
410 | } | 410 | } |
411 | 411 | ||
412 | sizecell = fdt_getprop(blob, 0, "#size-cells", NULL); | 412 | sizecell = fdt_getprop(blob, 0, "#size-cells", NULL); |
413 | /* use shifts and mask to ensure endianness */ | 413 | /* use shifts and mask to ensure endianness */ |
414 | if ((sizecell) && (*sizecell == 2)) { | 414 | if ((sizecell) && (*sizecell == 2)) { |
415 | tmp[0+len] = (size >> 56) & 0xff; | 415 | tmp[0+len] = (size >> 56) & 0xff; |
416 | tmp[1+len] = (size >> 48) & 0xff; | 416 | tmp[1+len] = (size >> 48) & 0xff; |
417 | tmp[2+len] = (size >> 40) & 0xff; | 417 | tmp[2+len] = (size >> 40) & 0xff; |
418 | tmp[3+len] = (size >> 32) & 0xff; | 418 | tmp[3+len] = (size >> 32) & 0xff; |
419 | tmp[4+len] = (size >> 24) & 0xff; | 419 | tmp[4+len] = (size >> 24) & 0xff; |
420 | tmp[5+len] = (size >> 16) & 0xff; | 420 | tmp[5+len] = (size >> 16) & 0xff; |
421 | tmp[6+len] = (size >> 8) & 0xff; | 421 | tmp[6+len] = (size >> 8) & 0xff; |
422 | tmp[7+len] = (size ) & 0xff; | 422 | tmp[7+len] = (size ) & 0xff; |
423 | len += 8; | 423 | len += 8; |
424 | } else { | 424 | } else { |
425 | tmp[0+len] = (size >> 24) & 0xff; | 425 | tmp[0+len] = (size >> 24) & 0xff; |
426 | tmp[1+len] = (size >> 16) & 0xff; | 426 | tmp[1+len] = (size >> 16) & 0xff; |
427 | tmp[2+len] = (size >> 8) & 0xff; | 427 | tmp[2+len] = (size >> 8) & 0xff; |
428 | tmp[3+len] = (size ) & 0xff; | 428 | tmp[3+len] = (size ) & 0xff; |
429 | len += 4; | 429 | len += 4; |
430 | } | 430 | } |
431 | 431 | ||
432 | err = fdt_setprop(blob, nodeoffset, "reg", tmp, len); | 432 | err = fdt_setprop(blob, nodeoffset, "reg", tmp, len); |
433 | if (err < 0) { | 433 | if (err < 0) { |
434 | printf("WARNING: could not set %s %s.\n", | 434 | printf("WARNING: could not set %s %s.\n", |
435 | "reg", fdt_strerror(err)); | 435 | "reg", fdt_strerror(err)); |
436 | return err; | 436 | return err; |
437 | } | 437 | } |
438 | return 0; | 438 | return 0; |
439 | } | 439 | } |
440 | 440 | ||
441 | void fdt_fixup_ethernet(void *fdt) | 441 | void fdt_fixup_ethernet(void *fdt) |
442 | { | 442 | { |
443 | int node, i, j; | 443 | int node, i, j; |
444 | char enet[16], *tmp, *end; | 444 | char enet[16], *tmp, *end; |
445 | char mac[16] = "ethaddr"; | 445 | char mac[16] = "ethaddr"; |
446 | const char *path; | 446 | const char *path; |
447 | unsigned char mac_addr[6]; | 447 | unsigned char mac_addr[6]; |
448 | 448 | ||
449 | node = fdt_path_offset(fdt, "/aliases"); | 449 | node = fdt_path_offset(fdt, "/aliases"); |
450 | if (node < 0) | 450 | if (node < 0) |
451 | return; | 451 | return; |
452 | 452 | ||
453 | i = 0; | 453 | i = 0; |
454 | while ((tmp = getenv(mac)) != NULL) { | 454 | while ((tmp = getenv(mac)) != NULL) { |
455 | sprintf(enet, "ethernet%d", i); | 455 | sprintf(enet, "ethernet%d", i); |
456 | path = fdt_getprop(fdt, node, enet, NULL); | 456 | path = fdt_getprop(fdt, node, enet, NULL); |
457 | if (!path) { | 457 | if (!path) { |
458 | debug("No alias for %s\n", enet); | 458 | debug("No alias for %s\n", enet); |
459 | sprintf(mac, "eth%daddr", ++i); | 459 | sprintf(mac, "eth%daddr", ++i); |
460 | continue; | 460 | continue; |
461 | } | 461 | } |
462 | 462 | ||
463 | for (j = 0; j < 6; j++) { | 463 | for (j = 0; j < 6; j++) { |
464 | mac_addr[j] = tmp ? simple_strtoul(tmp, &end, 16) : 0; | 464 | mac_addr[j] = tmp ? simple_strtoul(tmp, &end, 16) : 0; |
465 | if (tmp) | 465 | if (tmp) |
466 | tmp = (*end) ? end+1 : end; | 466 | tmp = (*end) ? end+1 : end; |
467 | } | 467 | } |
468 | 468 | ||
469 | do_fixup_by_path(fdt, path, "mac-address", &mac_addr, 6, 0); | 469 | do_fixup_by_path(fdt, path, "mac-address", &mac_addr, 6, 0); |
470 | do_fixup_by_path(fdt, path, "local-mac-address", | 470 | do_fixup_by_path(fdt, path, "local-mac-address", |
471 | &mac_addr, 6, 1); | 471 | &mac_addr, 6, 1); |
472 | 472 | ||
473 | sprintf(mac, "eth%daddr", ++i); | 473 | sprintf(mac, "eth%daddr", ++i); |
474 | } | 474 | } |
475 | } | 475 | } |
476 | 476 | ||
477 | #ifdef CONFIG_HAS_FSL_DR_USB | 477 | #ifdef CONFIG_HAS_FSL_DR_USB |
478 | void fdt_fixup_dr_usb(void *blob, bd_t *bd) | 478 | void fdt_fixup_dr_usb(void *blob, bd_t *bd) |
479 | { | 479 | { |
480 | char *mode; | 480 | char *mode; |
481 | char *type; | 481 | char *type; |
482 | const char *compat = "fsl-usb2-dr"; | 482 | const char *compat = "fsl-usb2-dr"; |
483 | const char *prop_mode = "dr_mode"; | 483 | const char *prop_mode = "dr_mode"; |
484 | const char *prop_type = "phy_type"; | 484 | const char *prop_type = "phy_type"; |
485 | int node_offset; | 485 | int node_offset; |
486 | int err; | 486 | int err; |
487 | 487 | ||
488 | mode = getenv("usb_dr_mode"); | 488 | mode = getenv("usb_dr_mode"); |
489 | type = getenv("usb_phy_type"); | 489 | type = getenv("usb_phy_type"); |
490 | if (!mode && !type) | 490 | if (!mode && !type) |
491 | return; | 491 | return; |
492 | 492 | ||
493 | node_offset = fdt_node_offset_by_compatible(blob, 0, compat); | 493 | node_offset = fdt_node_offset_by_compatible(blob, 0, compat); |
494 | if (node_offset < 0) { | 494 | if (node_offset < 0) { |
495 | printf("WARNING: could not find compatible node %s: %s.\n", | 495 | printf("WARNING: could not find compatible node %s: %s.\n", |
496 | compat, fdt_strerror(node_offset)); | 496 | compat, fdt_strerror(node_offset)); |
497 | return; | 497 | return; |
498 | } | 498 | } |
499 | 499 | ||
500 | if (mode) { | 500 | if (mode) { |
501 | err = fdt_setprop(blob, node_offset, prop_mode, mode, | 501 | err = fdt_setprop(blob, node_offset, prop_mode, mode, |
502 | strlen(mode) + 1); | 502 | strlen(mode) + 1); |
503 | if (err < 0) | 503 | if (err < 0) |
504 | printf("WARNING: could not set %s for %s: %s.\n", | 504 | printf("WARNING: could not set %s for %s: %s.\n", |
505 | prop_mode, compat, fdt_strerror(err)); | 505 | prop_mode, compat, fdt_strerror(err)); |
506 | } | 506 | } |
507 | 507 | ||
508 | if (type) { | 508 | if (type) { |
509 | err = fdt_setprop(blob, node_offset, prop_type, type, | 509 | err = fdt_setprop(blob, node_offset, prop_type, type, |
510 | strlen(type) + 1); | 510 | strlen(type) + 1); |
511 | if (err < 0) | 511 | if (err < 0) |
512 | printf("WARNING: could not set %s for %s: %s.\n", | 512 | printf("WARNING: could not set %s for %s: %s.\n", |
513 | prop_type, compat, fdt_strerror(err)); | 513 | prop_type, compat, fdt_strerror(err)); |
514 | } | 514 | } |
515 | } | 515 | } |
516 | #endif /* CONFIG_HAS_FSL_DR_USB */ | 516 | #endif /* CONFIG_HAS_FSL_DR_USB */ |
517 | 517 | ||
518 | #if defined(CONFIG_MPC83xx) || defined(CONFIG_MPC85xx) | 518 | #if defined(CONFIG_MPC83xx) || defined(CONFIG_MPC85xx) |
519 | /* | 519 | /* |
520 | * update crypto node properties to a specified revision of the SEC | 520 | * update crypto node properties to a specified revision of the SEC |
521 | * called with sec_rev == 0 if not on an mpc8xxxE processor | 521 | * called with sec_rev == 0 if not on an mpc8xxxE processor |
522 | */ | 522 | */ |
523 | void fdt_fixup_crypto_node(void *blob, int sec_rev) | 523 | void fdt_fixup_crypto_node(void *blob, int sec_rev) |
524 | { | 524 | { |
525 | const struct sec_rev_prop { | 525 | const struct sec_rev_prop { |
526 | u32 sec_rev; | 526 | u32 sec_rev; |
527 | u32 num_channels; | 527 | u32 num_channels; |
528 | u32 channel_fifo_len; | 528 | u32 channel_fifo_len; |
529 | u32 exec_units_mask; | 529 | u32 exec_units_mask; |
530 | u32 descriptor_types_mask; | 530 | u32 descriptor_types_mask; |
531 | } sec_rev_prop_list [] = { | 531 | } sec_rev_prop_list [] = { |
532 | { 0x0200, 4, 24, 0x07e, 0x01010ebf }, /* SEC 2.0 */ | 532 | { 0x0200, 4, 24, 0x07e, 0x01010ebf }, /* SEC 2.0 */ |
533 | { 0x0201, 4, 24, 0x0fe, 0x012b0ebf }, /* SEC 2.1 */ | 533 | { 0x0201, 4, 24, 0x0fe, 0x012b0ebf }, /* SEC 2.1 */ |
534 | { 0x0202, 1, 24, 0x04c, 0x0122003f }, /* SEC 2.2 */ | 534 | { 0x0202, 1, 24, 0x04c, 0x0122003f }, /* SEC 2.2 */ |
535 | { 0x0204, 4, 24, 0x07e, 0x012b0ebf }, /* SEC 2.4 */ | 535 | { 0x0204, 4, 24, 0x07e, 0x012b0ebf }, /* SEC 2.4 */ |
536 | { 0x0300, 4, 24, 0x9fe, 0x03ab0ebf }, /* SEC 3.0 */ | 536 | { 0x0300, 4, 24, 0x9fe, 0x03ab0ebf }, /* SEC 3.0 */ |
537 | { 0x0303, 4, 24, 0x97c, 0x03ab0abf }, /* SEC 3.3 */ | 537 | { 0x0303, 4, 24, 0x97c, 0x03ab0abf }, /* SEC 3.3 */ |
538 | }; | 538 | }; |
539 | char compat_strlist[ARRAY_SIZE(sec_rev_prop_list) * | 539 | char compat_strlist[ARRAY_SIZE(sec_rev_prop_list) * |
540 | sizeof("fsl,secX.Y")]; | 540 | sizeof("fsl,secX.Y")]; |
541 | int crypto_node, sec_idx, err; | 541 | int crypto_node, sec_idx, err; |
542 | char *p; | 542 | char *p; |
543 | u32 val; | 543 | u32 val; |
544 | 544 | ||
545 | /* locate crypto node based on lowest common compatible */ | 545 | /* locate crypto node based on lowest common compatible */ |
546 | crypto_node = fdt_node_offset_by_compatible(blob, -1, "fsl,sec2.0"); | 546 | crypto_node = fdt_node_offset_by_compatible(blob, -1, "fsl,sec2.0"); |
547 | if (crypto_node == -FDT_ERR_NOTFOUND) | 547 | if (crypto_node == -FDT_ERR_NOTFOUND) |
548 | return; | 548 | return; |
549 | 549 | ||
550 | /* delete it if not on an E-processor */ | 550 | /* delete it if not on an E-processor */ |
551 | if (crypto_node > 0 && !sec_rev) { | 551 | if (crypto_node > 0 && !sec_rev) { |
552 | fdt_del_node(blob, crypto_node); | 552 | fdt_del_node(blob, crypto_node); |
553 | return; | 553 | return; |
554 | } | 554 | } |
555 | 555 | ||
556 | /* else we got called for possible uprev */ | 556 | /* else we got called for possible uprev */ |
557 | for (sec_idx = 0; sec_idx < ARRAY_SIZE(sec_rev_prop_list); sec_idx++) | 557 | for (sec_idx = 0; sec_idx < ARRAY_SIZE(sec_rev_prop_list); sec_idx++) |
558 | if (sec_rev_prop_list[sec_idx].sec_rev == sec_rev) | 558 | if (sec_rev_prop_list[sec_idx].sec_rev == sec_rev) |
559 | break; | 559 | break; |
560 | 560 | ||
561 | if (sec_idx == ARRAY_SIZE(sec_rev_prop_list)) { | 561 | if (sec_idx == ARRAY_SIZE(sec_rev_prop_list)) { |
562 | puts("warning: unknown SEC revision number\n"); | 562 | puts("warning: unknown SEC revision number\n"); |
563 | return; | 563 | return; |
564 | } | 564 | } |
565 | 565 | ||
566 | val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].num_channels); | 566 | val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].num_channels); |
567 | err = fdt_setprop(blob, crypto_node, "fsl,num-channels", &val, 4); | 567 | err = fdt_setprop(blob, crypto_node, "fsl,num-channels", &val, 4); |
568 | if (err < 0) | 568 | if (err < 0) |
569 | printf("WARNING: could not set crypto property: %s\n", | 569 | printf("WARNING: could not set crypto property: %s\n", |
570 | fdt_strerror(err)); | 570 | fdt_strerror(err)); |
571 | 571 | ||
572 | val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].descriptor_types_mask); | 572 | val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].descriptor_types_mask); |
573 | err = fdt_setprop(blob, crypto_node, "fsl,descriptor-types-mask", &val, 4); | 573 | err = fdt_setprop(blob, crypto_node, "fsl,descriptor-types-mask", &val, 4); |
574 | if (err < 0) | 574 | if (err < 0) |
575 | printf("WARNING: could not set crypto property: %s\n", | 575 | printf("WARNING: could not set crypto property: %s\n", |
576 | fdt_strerror(err)); | 576 | fdt_strerror(err)); |
577 | 577 | ||
578 | val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].exec_units_mask); | 578 | val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].exec_units_mask); |
579 | err = fdt_setprop(blob, crypto_node, "fsl,exec-units-mask", &val, 4); | 579 | err = fdt_setprop(blob, crypto_node, "fsl,exec-units-mask", &val, 4); |
580 | if (err < 0) | 580 | if (err < 0) |
581 | printf("WARNING: could not set crypto property: %s\n", | 581 | printf("WARNING: could not set crypto property: %s\n", |
582 | fdt_strerror(err)); | 582 | fdt_strerror(err)); |
583 | 583 | ||
584 | val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].channel_fifo_len); | 584 | val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].channel_fifo_len); |
585 | err = fdt_setprop(blob, crypto_node, "fsl,channel-fifo-len", &val, 4); | 585 | err = fdt_setprop(blob, crypto_node, "fsl,channel-fifo-len", &val, 4); |
586 | if (err < 0) | 586 | if (err < 0) |
587 | printf("WARNING: could not set crypto property: %s\n", | 587 | printf("WARNING: could not set crypto property: %s\n", |
588 | fdt_strerror(err)); | 588 | fdt_strerror(err)); |
589 | 589 | ||
590 | val = 0; | 590 | val = 0; |
591 | while (sec_idx >= 0) { | 591 | while (sec_idx >= 0) { |
592 | p = compat_strlist + val; | 592 | p = compat_strlist + val; |
593 | val += sprintf(p, "fsl,sec%d.%d", | 593 | val += sprintf(p, "fsl,sec%d.%d", |
594 | (sec_rev_prop_list[sec_idx].sec_rev & 0xff00) >> 8, | 594 | (sec_rev_prop_list[sec_idx].sec_rev & 0xff00) >> 8, |
595 | sec_rev_prop_list[sec_idx].sec_rev & 0x00ff) + 1; | 595 | sec_rev_prop_list[sec_idx].sec_rev & 0x00ff) + 1; |
596 | sec_idx--; | 596 | sec_idx--; |
597 | } | 597 | } |
598 | err = fdt_setprop(blob, crypto_node, "compatible", &compat_strlist, val); | 598 | err = fdt_setprop(blob, crypto_node, "compatible", &compat_strlist, val); |
599 | if (err < 0) | 599 | if (err < 0) |
600 | printf("WARNING: could not set crypto property: %s\n", | 600 | printf("WARNING: could not set crypto property: %s\n", |
601 | fdt_strerror(err)); | 601 | fdt_strerror(err)); |
602 | } | 602 | } |
603 | #endif /* defined(CONFIG_MPC83xx) || defined(CONFIG_MPC85xx) */ | 603 | #endif /* defined(CONFIG_MPC83xx) || defined(CONFIG_MPC85xx) */ |
604 | 604 | ||
605 | /* Resize the fdt to its actual size + a bit of padding */ | 605 | /* Resize the fdt to its actual size + a bit of padding */ |
606 | int fdt_resize(void *blob) | 606 | int fdt_resize(void *blob) |
607 | { | 607 | { |
608 | int i; | 608 | int i; |
609 | uint64_t addr, size; | 609 | uint64_t addr, size; |
610 | int total, ret; | 610 | int total, ret; |
611 | uint actualsize; | 611 | uint actualsize; |
612 | 612 | ||
613 | if (!blob) | 613 | if (!blob) |
614 | return 0; | 614 | return 0; |
615 | 615 | ||
616 | total = fdt_num_mem_rsv(blob); | 616 | total = fdt_num_mem_rsv(blob); |
617 | for (i = 0; i < total; i++) { | 617 | for (i = 0; i < total; i++) { |
618 | fdt_get_mem_rsv(blob, i, &addr, &size); | 618 | fdt_get_mem_rsv(blob, i, &addr, &size); |
619 | if (addr == (uint64_t)(u32)blob) { | 619 | if (addr == (uint64_t)(u32)blob) { |
620 | fdt_del_mem_rsv(blob, i); | 620 | fdt_del_mem_rsv(blob, i); |
621 | break; | 621 | break; |
622 | } | 622 | } |
623 | } | 623 | } |
624 | 624 | ||
625 | /* | 625 | /* |
626 | * Calculate the actual size of the fdt | 626 | * Calculate the actual size of the fdt |
627 | * plus the size needed for two fdt_add_mem_rsv, one | 627 | * plus the size needed for two fdt_add_mem_rsv, one |
628 | * for the fdt itself and one for a possible initrd | 628 | * for the fdt itself and one for a possible initrd |
629 | */ | 629 | */ |
630 | actualsize = fdt_off_dt_strings(blob) + | 630 | actualsize = fdt_off_dt_strings(blob) + |
631 | fdt_size_dt_strings(blob) + 2*sizeof(struct fdt_reserve_entry); | 631 | fdt_size_dt_strings(blob) + 2*sizeof(struct fdt_reserve_entry); |
632 | 632 | ||
633 | /* Make it so the fdt ends on a page boundary */ | 633 | /* Make it so the fdt ends on a page boundary */ |
634 | actualsize = ALIGN(actualsize + ((uint)blob & 0xfff), 0x1000); | 634 | actualsize = ALIGN(actualsize + ((uint)blob & 0xfff), 0x1000); |
635 | actualsize = actualsize - ((uint)blob & 0xfff); | 635 | actualsize = actualsize - ((uint)blob & 0xfff); |
636 | 636 | ||
637 | /* Change the fdt header to reflect the correct size */ | 637 | /* Change the fdt header to reflect the correct size */ |
638 | fdt_set_totalsize(blob, actualsize); | 638 | fdt_set_totalsize(blob, actualsize); |
639 | 639 | ||
640 | /* Add the new reservation */ | 640 | /* Add the new reservation */ |
641 | ret = fdt_add_mem_rsv(blob, (uint)blob, actualsize); | 641 | ret = fdt_add_mem_rsv(blob, (uint)blob, actualsize); |
642 | if (ret < 0) | 642 | if (ret < 0) |
643 | return ret; | 643 | return ret; |
644 | 644 | ||
645 | return actualsize; | 645 | return actualsize; |
646 | } | 646 | } |
647 | 647 | ||
648 | #ifdef CONFIG_PCI | 648 | #ifdef CONFIG_PCI |
649 | #define CONFIG_SYS_PCI_NR_INBOUND_WIN 4 | 649 | #define CONFIG_SYS_PCI_NR_INBOUND_WIN 4 |
650 | 650 | ||
651 | #define FDT_PCI_PREFETCH (0x40000000) | 651 | #define FDT_PCI_PREFETCH (0x40000000) |
652 | #define FDT_PCI_MEM32 (0x02000000) | 652 | #define FDT_PCI_MEM32 (0x02000000) |
653 | #define FDT_PCI_IO (0x01000000) | 653 | #define FDT_PCI_IO (0x01000000) |
654 | #define FDT_PCI_MEM64 (0x03000000) | 654 | #define FDT_PCI_MEM64 (0x03000000) |
655 | 655 | ||
656 | int fdt_pci_dma_ranges(void *blob, int phb_off, struct pci_controller *hose) { | 656 | int fdt_pci_dma_ranges(void *blob, int phb_off, struct pci_controller *hose) { |
657 | 657 | ||
658 | int addrcell, sizecell, len, r; | 658 | int addrcell, sizecell, len, r; |
659 | u32 *dma_range; | 659 | u32 *dma_range; |
660 | /* sized based on pci addr cells, size-cells, & address-cells */ | 660 | /* sized based on pci addr cells, size-cells, & address-cells */ |
661 | u32 dma_ranges[(3 + 2 + 2) * CONFIG_SYS_PCI_NR_INBOUND_WIN]; | 661 | u32 dma_ranges[(3 + 2 + 2) * CONFIG_SYS_PCI_NR_INBOUND_WIN]; |
662 | 662 | ||
663 | addrcell = fdt_getprop_u32_default(blob, "/", "#address-cells", 1); | 663 | addrcell = fdt_getprop_u32_default(blob, "/", "#address-cells", 1); |
664 | sizecell = fdt_getprop_u32_default(blob, "/", "#size-cells", 1); | 664 | sizecell = fdt_getprop_u32_default(blob, "/", "#size-cells", 1); |
665 | 665 | ||
666 | dma_range = &dma_ranges[0]; | 666 | dma_range = &dma_ranges[0]; |
667 | for (r = 0; r < hose->region_count; r++) { | 667 | for (r = 0; r < hose->region_count; r++) { |
668 | u64 bus_start, phys_start, size; | 668 | u64 bus_start, phys_start, size; |
669 | 669 | ||
670 | /* skip if !PCI_REGION_SYS_MEMORY */ | 670 | /* skip if !PCI_REGION_SYS_MEMORY */ |
671 | if (!(hose->regions[r].flags & PCI_REGION_SYS_MEMORY)) | 671 | if (!(hose->regions[r].flags & PCI_REGION_SYS_MEMORY)) |
672 | continue; | 672 | continue; |
673 | 673 | ||
674 | bus_start = (u64)hose->regions[r].bus_start; | 674 | bus_start = (u64)hose->regions[r].bus_start; |
675 | phys_start = (u64)hose->regions[r].phys_start; | 675 | phys_start = (u64)hose->regions[r].phys_start; |
676 | size = (u64)hose->regions[r].size; | 676 | size = (u64)hose->regions[r].size; |
677 | 677 | ||
678 | dma_range[0] = 0; | 678 | dma_range[0] = 0; |
679 | if (size >= 0x100000000ull) | 679 | if (size >= 0x100000000ull) |
680 | dma_range[0] |= FDT_PCI_MEM64; | 680 | dma_range[0] |= FDT_PCI_MEM64; |
681 | else | 681 | else |
682 | dma_range[0] |= FDT_PCI_MEM32; | 682 | dma_range[0] |= FDT_PCI_MEM32; |
683 | if (hose->regions[r].flags & PCI_REGION_PREFETCH) | 683 | if (hose->regions[r].flags & PCI_REGION_PREFETCH) |
684 | dma_range[0] |= FDT_PCI_PREFETCH; | 684 | dma_range[0] |= FDT_PCI_PREFETCH; |
685 | #ifdef CONFIG_SYS_PCI_64BIT | 685 | #ifdef CONFIG_SYS_PCI_64BIT |
686 | dma_range[1] = bus_start >> 32; | 686 | dma_range[1] = bus_start >> 32; |
687 | #else | 687 | #else |
688 | dma_range[1] = 0; | 688 | dma_range[1] = 0; |
689 | #endif | 689 | #endif |
690 | dma_range[2] = bus_start & 0xffffffff; | 690 | dma_range[2] = bus_start & 0xffffffff; |
691 | 691 | ||
692 | if (addrcell == 2) { | 692 | if (addrcell == 2) { |
693 | dma_range[3] = phys_start >> 32; | 693 | dma_range[3] = phys_start >> 32; |
694 | dma_range[4] = phys_start & 0xffffffff; | 694 | dma_range[4] = phys_start & 0xffffffff; |
695 | } else { | 695 | } else { |
696 | dma_range[3] = phys_start & 0xffffffff; | 696 | dma_range[3] = phys_start & 0xffffffff; |
697 | } | 697 | } |
698 | 698 | ||
699 | if (sizecell == 2) { | 699 | if (sizecell == 2) { |
700 | dma_range[3 + addrcell + 0] = size >> 32; | 700 | dma_range[3 + addrcell + 0] = size >> 32; |
701 | dma_range[3 + addrcell + 1] = size & 0xffffffff; | 701 | dma_range[3 + addrcell + 1] = size & 0xffffffff; |
702 | } else { | 702 | } else { |
703 | dma_range[3 + addrcell + 0] = size & 0xffffffff; | 703 | dma_range[3 + addrcell + 0] = size & 0xffffffff; |
704 | } | 704 | } |
705 | 705 | ||
706 | dma_range += (3 + addrcell + sizecell); | 706 | dma_range += (3 + addrcell + sizecell); |
707 | } | 707 | } |
708 | 708 | ||
709 | len = dma_range - &dma_ranges[0]; | 709 | len = dma_range - &dma_ranges[0]; |
710 | if (len) | 710 | if (len) |
711 | fdt_setprop(blob, phb_off, "dma-ranges", &dma_ranges[0], len*4); | 711 | fdt_setprop(blob, phb_off, "dma-ranges", &dma_ranges[0], len*4); |
712 | 712 | ||
713 | return 0; | 713 | return 0; |
714 | } | 714 | } |
715 | #endif | 715 | #endif |
716 | 716 | ||
717 | #ifdef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE | 717 | #ifdef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE |
718 | /* | 718 | /* |
719 | * This function can be used to update the size in the "reg" property | 719 | * This function can be used to update the size in the "reg" property |
720 | * of the NOR FLASH device nodes. This is necessary for boards with | 720 | * of the NOR FLASH device nodes. This is necessary for boards with |
721 | * non-fixed NOR FLASH sizes. | 721 | * non-fixed NOR FLASH sizes. |
722 | */ | 722 | */ |
723 | int fdt_fixup_nor_flash_size(void *blob, int cs, u32 size) | 723 | int fdt_fixup_nor_flash_size(void *blob, int cs, u32 size) |
724 | { | 724 | { |
725 | char compat[][16] = { "cfi-flash", "jedec-flash" }; | 725 | char compat[][16] = { "cfi-flash", "jedec-flash" }; |
726 | int off; | 726 | int off; |
727 | int len; | 727 | int len; |
728 | struct fdt_property *prop; | 728 | struct fdt_property *prop; |
729 | u32 *reg; | 729 | u32 *reg; |
730 | int i; | 730 | int i; |
731 | 731 | ||
732 | for (i = 0; i < 2; i++) { | 732 | for (i = 0; i < 2; i++) { |
733 | off = fdt_node_offset_by_compatible(blob, -1, compat[i]); | 733 | off = fdt_node_offset_by_compatible(blob, -1, compat[i]); |
734 | while (off != -FDT_ERR_NOTFOUND) { | 734 | while (off != -FDT_ERR_NOTFOUND) { |
735 | /* | 735 | /* |
736 | * Found one compatible node, now check if this one | 736 | * Found one compatible node, now check if this one |
737 | * has the correct CS | 737 | * has the correct CS |
738 | */ | 738 | */ |
739 | prop = fdt_get_property_w(blob, off, "reg", &len); | 739 | prop = fdt_get_property_w(blob, off, "reg", &len); |
740 | if (prop) { | 740 | if (prop) { |
741 | reg = (u32 *)&prop->data[0]; | 741 | reg = (u32 *)&prop->data[0]; |
742 | if (reg[0] == cs) { | 742 | if (reg[0] == cs) { |
743 | reg[2] = size; | 743 | reg[2] = size; |
744 | fdt_setprop(blob, off, "reg", reg, | 744 | fdt_setprop(blob, off, "reg", reg, |
745 | 3 * sizeof(u32)); | 745 | 3 * sizeof(u32)); |
746 | 746 | ||
747 | return 0; | 747 | return 0; |
748 | } | 748 | } |
749 | } | 749 | } |
750 | 750 | ||
751 | /* Move to next compatible node */ | 751 | /* Move to next compatible node */ |
752 | off = fdt_node_offset_by_compatible(blob, off, | 752 | off = fdt_node_offset_by_compatible(blob, off, |
753 | compat[i]); | 753 | compat[i]); |
754 | } | 754 | } |
755 | } | 755 | } |
756 | 756 | ||
757 | return -1; | 757 | return -1; |
758 | } | 758 | } |
759 | #endif | 759 | #endif |
760 | 760 | ||
761 | #ifdef CONFIG_FDT_FIXUP_PARTITIONS | 761 | #ifdef CONFIG_FDT_FIXUP_PARTITIONS |
762 | #include <jffs2/load_kernel.h> | 762 | #include <jffs2/load_kernel.h> |
763 | #include <mtd_node.h> | 763 | #include <mtd_node.h> |
764 | 764 | ||
765 | struct reg_cell { | 765 | struct reg_cell { |
766 | unsigned int r0; | 766 | unsigned int r0; |
767 | unsigned int r1; | 767 | unsigned int r1; |
768 | }; | 768 | }; |
769 | 769 | ||
770 | int fdt_del_subnodes(const void *blob, int parent_offset) | 770 | int fdt_del_subnodes(const void *blob, int parent_offset) |
771 | { | 771 | { |
772 | int off, ndepth; | 772 | int off, ndepth; |
773 | int ret; | 773 | int ret; |
774 | 774 | ||
775 | for (ndepth = 0, off = fdt_next_node(blob, parent_offset, &ndepth); | 775 | for (ndepth = 0, off = fdt_next_node(blob, parent_offset, &ndepth); |
776 | (off >= 0) && (ndepth > 0); | 776 | (off >= 0) && (ndepth > 0); |
777 | off = fdt_next_node(blob, off, &ndepth)) { | 777 | off = fdt_next_node(blob, off, &ndepth)) { |
778 | if (ndepth == 1) { | 778 | if (ndepth == 1) { |
779 | debug("delete %s: offset: %x\n", | 779 | debug("delete %s: offset: %x\n", |
780 | fdt_get_name(blob, off, 0), off); | 780 | fdt_get_name(blob, off, 0), off); |
781 | ret = fdt_del_node((void *)blob, off); | 781 | ret = fdt_del_node((void *)blob, off); |
782 | if (ret < 0) { | 782 | if (ret < 0) { |
783 | printf("Can't delete node: %s\n", | 783 | printf("Can't delete node: %s\n", |
784 | fdt_strerror(ret)); | 784 | fdt_strerror(ret)); |
785 | return ret; | 785 | return ret; |
786 | } else { | 786 | } else { |
787 | ndepth = 0; | 787 | ndepth = 0; |
788 | off = parent_offset; | 788 | off = parent_offset; |
789 | } | 789 | } |
790 | } | 790 | } |
791 | } | 791 | } |
792 | return 0; | 792 | return 0; |
793 | } | 793 | } |
794 | 794 | ||
795 | int fdt_increase_size(void *fdt, int add_len) | 795 | int fdt_increase_size(void *fdt, int add_len) |
796 | { | 796 | { |
797 | int newlen; | 797 | int newlen; |
798 | 798 | ||
799 | newlen = fdt_totalsize(fdt) + add_len; | 799 | newlen = fdt_totalsize(fdt) + add_len; |
800 | 800 | ||
801 | /* Open in place with a new len */ | 801 | /* Open in place with a new len */ |
802 | return fdt_open_into(fdt, fdt, newlen); | 802 | return fdt_open_into(fdt, fdt, newlen); |
803 | } | 803 | } |
804 | 804 | ||
805 | int fdt_del_partitions(void *blob, int parent_offset) | 805 | int fdt_del_partitions(void *blob, int parent_offset) |
806 | { | 806 | { |
807 | const void *prop; | 807 | const void *prop; |
808 | int ndepth = 0; | 808 | int ndepth = 0; |
809 | int off; | 809 | int off; |
810 | int ret; | 810 | int ret; |
811 | 811 | ||
812 | off = fdt_next_node(blob, parent_offset, &ndepth); | 812 | off = fdt_next_node(blob, parent_offset, &ndepth); |
813 | if (off > 0 && ndepth == 1) { | 813 | if (off > 0 && ndepth == 1) { |
814 | prop = fdt_getprop(blob, off, "label", NULL); | 814 | prop = fdt_getprop(blob, off, "label", NULL); |
815 | if (prop == NULL) { | 815 | if (prop == NULL) { |
816 | /* | 816 | /* |
817 | * Could not find label property, nand {}; node? | 817 | * Could not find label property, nand {}; node? |
818 | * Check subnode, delete partitions there if any. | 818 | * Check subnode, delete partitions there if any. |
819 | */ | 819 | */ |
820 | return fdt_del_partitions(blob, off); | 820 | return fdt_del_partitions(blob, off); |
821 | } else { | 821 | } else { |
822 | ret = fdt_del_subnodes(blob, parent_offset); | 822 | ret = fdt_del_subnodes(blob, parent_offset); |
823 | if (ret < 0) { | 823 | if (ret < 0) { |
824 | printf("Can't remove subnodes: %s\n", | 824 | printf("Can't remove subnodes: %s\n", |
825 | fdt_strerror(ret)); | 825 | fdt_strerror(ret)); |
826 | return ret; | 826 | return ret; |
827 | } | 827 | } |
828 | } | 828 | } |
829 | } | 829 | } |
830 | return 0; | 830 | return 0; |
831 | } | 831 | } |
832 | 832 | ||
833 | int fdt_node_set_part_info(void *blob, int parent_offset, | 833 | int fdt_node_set_part_info(void *blob, int parent_offset, |
834 | struct mtd_device *dev) | 834 | struct mtd_device *dev) |
835 | { | 835 | { |
836 | struct list_head *pentry; | 836 | struct list_head *pentry; |
837 | struct part_info *part; | 837 | struct part_info *part; |
838 | struct reg_cell cell; | 838 | struct reg_cell cell; |
839 | int off, ndepth = 0; | 839 | int off, ndepth = 0; |
840 | int part_num, ret; | 840 | int part_num, ret; |
841 | char buf[64]; | 841 | char buf[64]; |
842 | 842 | ||
843 | ret = fdt_del_partitions(blob, parent_offset); | 843 | ret = fdt_del_partitions(blob, parent_offset); |
844 | if (ret < 0) | 844 | if (ret < 0) |
845 | return ret; | 845 | return ret; |
846 | 846 | ||
847 | /* | 847 | /* |
848 | * Check if it is nand {}; subnode, adjust | 848 | * Check if it is nand {}; subnode, adjust |
849 | * the offset in this case | 849 | * the offset in this case |
850 | */ | 850 | */ |
851 | off = fdt_next_node(blob, parent_offset, &ndepth); | 851 | off = fdt_next_node(blob, parent_offset, &ndepth); |
852 | if (off > 0 && ndepth == 1) | 852 | if (off > 0 && ndepth == 1) |
853 | parent_offset = off; | 853 | parent_offset = off; |
854 | 854 | ||
855 | part_num = 0; | 855 | part_num = 0; |
856 | list_for_each_prev(pentry, &dev->parts) { | 856 | list_for_each_prev(pentry, &dev->parts) { |
857 | int newoff; | 857 | int newoff; |
858 | 858 | ||
859 | part = list_entry(pentry, struct part_info, link); | 859 | part = list_entry(pentry, struct part_info, link); |
860 | 860 | ||
861 | debug("%2d: %-20s0x%08x\t0x%08x\t%d\n", | 861 | debug("%2d: %-20s0x%08x\t0x%08x\t%d\n", |
862 | part_num, part->name, part->size, | 862 | part_num, part->name, part->size, |
863 | part->offset, part->mask_flags); | 863 | part->offset, part->mask_flags); |
864 | 864 | ||
865 | sprintf(buf, "partition@%x", part->offset); | 865 | sprintf(buf, "partition@%x", part->offset); |
866 | add_sub: | 866 | add_sub: |
867 | ret = fdt_add_subnode(blob, parent_offset, buf); | 867 | ret = fdt_add_subnode(blob, parent_offset, buf); |
868 | if (ret == -FDT_ERR_NOSPACE) { | 868 | if (ret == -FDT_ERR_NOSPACE) { |
869 | ret = fdt_increase_size(blob, 512); | 869 | ret = fdt_increase_size(blob, 512); |
870 | if (!ret) | 870 | if (!ret) |
871 | goto add_sub; | 871 | goto add_sub; |
872 | else | 872 | else |
873 | goto err_size; | 873 | goto err_size; |
874 | } else if (ret < 0) { | 874 | } else if (ret < 0) { |
875 | printf("Can't add partition node: %s\n", | 875 | printf("Can't add partition node: %s\n", |
876 | fdt_strerror(ret)); | 876 | fdt_strerror(ret)); |
877 | return ret; | 877 | return ret; |
878 | } | 878 | } |
879 | newoff = ret; | 879 | newoff = ret; |
880 | 880 | ||
881 | /* Check MTD_WRITEABLE_CMD flag */ | 881 | /* Check MTD_WRITEABLE_CMD flag */ |
882 | if (part->mask_flags & 1) { | 882 | if (part->mask_flags & 1) { |
883 | add_ro: | 883 | add_ro: |
884 | ret = fdt_setprop(blob, newoff, "read_only", NULL, 0); | 884 | ret = fdt_setprop(blob, newoff, "read_only", NULL, 0); |
885 | if (ret == -FDT_ERR_NOSPACE) { | 885 | if (ret == -FDT_ERR_NOSPACE) { |
886 | ret = fdt_increase_size(blob, 512); | 886 | ret = fdt_increase_size(blob, 512); |
887 | if (!ret) | 887 | if (!ret) |
888 | goto add_ro; | 888 | goto add_ro; |
889 | else | 889 | else |
890 | goto err_size; | 890 | goto err_size; |
891 | } else if (ret < 0) | 891 | } else if (ret < 0) |
892 | goto err_prop; | 892 | goto err_prop; |
893 | } | 893 | } |
894 | 894 | ||
895 | cell.r0 = cpu_to_fdt32(part->offset); | 895 | cell.r0 = cpu_to_fdt32(part->offset); |
896 | cell.r1 = cpu_to_fdt32(part->size); | 896 | cell.r1 = cpu_to_fdt32(part->size); |
897 | add_reg: | 897 | add_reg: |
898 | ret = fdt_setprop(blob, newoff, "reg", &cell, sizeof(cell)); | 898 | ret = fdt_setprop(blob, newoff, "reg", &cell, sizeof(cell)); |
899 | if (ret == -FDT_ERR_NOSPACE) { | 899 | if (ret == -FDT_ERR_NOSPACE) { |
900 | ret = fdt_increase_size(blob, 512); | 900 | ret = fdt_increase_size(blob, 512); |
901 | if (!ret) | 901 | if (!ret) |
902 | goto add_reg; | 902 | goto add_reg; |
903 | else | 903 | else |
904 | goto err_size; | 904 | goto err_size; |
905 | } else if (ret < 0) | 905 | } else if (ret < 0) |
906 | goto err_prop; | 906 | goto err_prop; |
907 | 907 | ||
908 | add_label: | 908 | add_label: |
909 | ret = fdt_setprop_string(blob, newoff, "label", part->name); | 909 | ret = fdt_setprop_string(blob, newoff, "label", part->name); |
910 | if (ret == -FDT_ERR_NOSPACE) { | 910 | if (ret == -FDT_ERR_NOSPACE) { |
911 | ret = fdt_increase_size(blob, 512); | 911 | ret = fdt_increase_size(blob, 512); |
912 | if (!ret) | 912 | if (!ret) |
913 | goto add_label; | 913 | goto add_label; |
914 | else | 914 | else |
915 | goto err_size; | 915 | goto err_size; |
916 | } else if (ret < 0) | 916 | } else if (ret < 0) |
917 | goto err_prop; | 917 | goto err_prop; |
918 | 918 | ||
919 | part_num++; | 919 | part_num++; |
920 | } | 920 | } |
921 | return 0; | 921 | return 0; |
922 | err_size: | 922 | err_size: |
923 | printf("Can't increase blob size: %s\n", fdt_strerror(ret)); | 923 | printf("Can't increase blob size: %s\n", fdt_strerror(ret)); |
924 | return ret; | 924 | return ret; |
925 | err_prop: | 925 | err_prop: |
926 | printf("Can't add property: %s\n", fdt_strerror(ret)); | 926 | printf("Can't add property: %s\n", fdt_strerror(ret)); |
927 | return ret; | 927 | return ret; |
928 | } | 928 | } |
929 | 929 | ||
930 | /* | 930 | /* |
931 | * Update partitions in nor/nand nodes using info from | 931 | * Update partitions in nor/nand nodes using info from |
932 | * mtdparts environment variable. The nodes to update are | 932 | * mtdparts environment variable. The nodes to update are |
933 | * specified by node_info structure which contains mtd device | 933 | * specified by node_info structure which contains mtd device |
934 | * type and compatible string: E. g. the board code in | 934 | * type and compatible string: E. g. the board code in |
935 | * ft_board_setup() could use: | 935 | * ft_board_setup() could use: |
936 | * | 936 | * |
937 | * struct node_info nodes[] = { | 937 | * struct node_info nodes[] = { |
938 | * { "fsl,mpc5121-nfc", MTD_DEV_TYPE_NAND, }, | 938 | * { "fsl,mpc5121-nfc", MTD_DEV_TYPE_NAND, }, |
939 | * { "cfi-flash", MTD_DEV_TYPE_NOR, }, | 939 | * { "cfi-flash", MTD_DEV_TYPE_NOR, }, |
940 | * }; | 940 | * }; |
941 | * | 941 | * |
942 | * fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes)); | 942 | * fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes)); |
943 | */ | 943 | */ |
944 | void fdt_fixup_mtdparts(void *blob, void *node_info, int node_info_size) | 944 | void fdt_fixup_mtdparts(void *blob, void *node_info, int node_info_size) |
945 | { | 945 | { |
946 | struct node_info *ni = node_info; | 946 | struct node_info *ni = node_info; |
947 | struct mtd_device *dev; | 947 | struct mtd_device *dev; |
948 | char *parts; | 948 | char *parts; |
949 | int i, idx; | 949 | int i, idx; |
950 | int noff; | 950 | int noff; |
951 | 951 | ||
952 | parts = getenv("mtdparts"); | 952 | parts = getenv("mtdparts"); |
953 | if (!parts) | 953 | if (!parts) |
954 | return; | 954 | return; |
955 | 955 | ||
956 | if (mtdparts_init() != 0) | 956 | if (mtdparts_init() != 0) |
957 | return; | 957 | return; |
958 | 958 | ||
959 | for (i = 0; i < node_info_size; i++) { | 959 | for (i = 0; i < node_info_size; i++) { |
960 | idx = 0; | 960 | idx = 0; |
961 | noff = fdt_node_offset_by_compatible(blob, -1, ni[i].compat); | 961 | noff = fdt_node_offset_by_compatible(blob, -1, ni[i].compat); |
962 | while (noff != -FDT_ERR_NOTFOUND) { | 962 | while (noff != -FDT_ERR_NOTFOUND) { |
963 | debug("%s: %s, mtd dev type %d\n", | 963 | debug("%s: %s, mtd dev type %d\n", |
964 | fdt_get_name(blob, noff, 0), | 964 | fdt_get_name(blob, noff, 0), |
965 | ni[i].compat, ni[i].type); | 965 | ni[i].compat, ni[i].type); |
966 | dev = device_find(ni[i].type, idx++); | 966 | dev = device_find(ni[i].type, idx++); |
967 | if (dev) { | 967 | if (dev) { |
968 | if (fdt_node_set_part_info(blob, noff, dev)) | 968 | if (fdt_node_set_part_info(blob, noff, dev)) |
969 | return; /* return on error */ | 969 | return; /* return on error */ |
970 | } | 970 | } |
971 | 971 | ||
972 | /* Jump to next flash node */ | 972 | /* Jump to next flash node */ |
973 | noff = fdt_node_offset_by_compatible(blob, noff, | 973 | noff = fdt_node_offset_by_compatible(blob, noff, |
974 | ni[i].compat); | 974 | ni[i].compat); |
975 | } | 975 | } |
976 | } | 976 | } |
977 | } | 977 | } |
978 | #endif | 978 | #endif |
979 | |||
980 | void fdt_del_node_and_alias(void *blob, const char *alias) | ||
981 | { | ||
982 | int off = fdt_path_offset(blob, alias); | ||
983 | |||
984 | if (off < 0) | ||
985 | return; | ||
986 | |||
987 | fdt_del_node(blob, off); | ||
988 | |||
989 | off = fdt_path_offset(blob, "/aliases"); | ||
990 | fdt_delprop(blob, off, alias); | ||
991 | } | ||
979 | 992 |
include/fdt_support.h
1 | /* | 1 | /* |
2 | * (C) Copyright 2007 | 2 | * (C) Copyright 2007 |
3 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com | 3 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com |
4 | * | 4 | * |
5 | * See file CREDITS for list of people who contributed to this | 5 | * See file CREDITS for list of people who contributed to this |
6 | * project. | 6 | * project. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License as | 9 | * modify it under the terms of the GNU General Public License as |
10 | * published by the Free Software Foundation; either version 2 of | 10 | * published by the Free Software Foundation; either version 2 of |
11 | * the License, or (at your option) any later version. | 11 | * the License, or (at your option) any later version. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
21 | * MA 02111-1307 USA | 21 | * MA 02111-1307 USA |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #ifndef __FDT_SUPPORT_H | 24 | #ifndef __FDT_SUPPORT_H |
25 | #define __FDT_SUPPORT_H | 25 | #define __FDT_SUPPORT_H |
26 | 26 | ||
27 | #ifdef CONFIG_OF_LIBFDT | 27 | #ifdef CONFIG_OF_LIBFDT |
28 | 28 | ||
29 | #include <fdt.h> | 29 | #include <fdt.h> |
30 | 30 | ||
31 | u32 fdt_getprop_u32_default(void *fdt, const char *path, const char *prop, | 31 | u32 fdt_getprop_u32_default(void *fdt, const char *path, const char *prop, |
32 | const u32 dflt); | 32 | const u32 dflt); |
33 | int fdt_chosen(void *fdt, int force); | 33 | int fdt_chosen(void *fdt, int force); |
34 | int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force); | 34 | int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force); |
35 | void do_fixup_by_path(void *fdt, const char *path, const char *prop, | 35 | void do_fixup_by_path(void *fdt, const char *path, const char *prop, |
36 | const void *val, int len, int create); | 36 | const void *val, int len, int create); |
37 | void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop, | 37 | void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop, |
38 | u32 val, int create); | 38 | u32 val, int create); |
39 | void do_fixup_by_prop(void *fdt, | 39 | void do_fixup_by_prop(void *fdt, |
40 | const char *pname, const void *pval, int plen, | 40 | const char *pname, const void *pval, int plen, |
41 | const char *prop, const void *val, int len, | 41 | const char *prop, const void *val, int len, |
42 | int create); | 42 | int create); |
43 | void do_fixup_by_prop_u32(void *fdt, | 43 | void do_fixup_by_prop_u32(void *fdt, |
44 | const char *pname, const void *pval, int plen, | 44 | const char *pname, const void *pval, int plen, |
45 | const char *prop, u32 val, int create); | 45 | const char *prop, u32 val, int create); |
46 | void do_fixup_by_compat(void *fdt, const char *compat, | 46 | void do_fixup_by_compat(void *fdt, const char *compat, |
47 | const char *prop, const void *val, int len, int create); | 47 | const char *prop, const void *val, int len, int create); |
48 | void do_fixup_by_compat_u32(void *fdt, const char *compat, | 48 | void do_fixup_by_compat_u32(void *fdt, const char *compat, |
49 | const char *prop, u32 val, int create); | 49 | const char *prop, u32 val, int create); |
50 | int fdt_fixup_memory(void *blob, u64 start, u64 size); | 50 | int fdt_fixup_memory(void *blob, u64 start, u64 size); |
51 | void fdt_fixup_ethernet(void *fdt); | 51 | void fdt_fixup_ethernet(void *fdt); |
52 | int fdt_find_and_setprop(void *fdt, const char *node, const char *prop, | 52 | int fdt_find_and_setprop(void *fdt, const char *node, const char *prop, |
53 | const void *val, int len, int create); | 53 | const void *val, int len, int create); |
54 | void fdt_fixup_qe_firmware(void *fdt); | 54 | void fdt_fixup_qe_firmware(void *fdt); |
55 | 55 | ||
56 | #ifdef CONFIG_HAS_FSL_DR_USB | 56 | #ifdef CONFIG_HAS_FSL_DR_USB |
57 | void fdt_fixup_dr_usb(void *blob, bd_t *bd); | 57 | void fdt_fixup_dr_usb(void *blob, bd_t *bd); |
58 | #else | 58 | #else |
59 | static inline void fdt_fixup_dr_usb(void *blob, bd_t *bd) {} | 59 | static inline void fdt_fixup_dr_usb(void *blob, bd_t *bd) {} |
60 | #endif /* CONFIG_HAS_FSL_DR_USB */ | 60 | #endif /* CONFIG_HAS_FSL_DR_USB */ |
61 | 61 | ||
62 | #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC83xx) | 62 | #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC83xx) |
63 | void fdt_fixup_crypto_node(void *blob, int sec_rev); | 63 | void fdt_fixup_crypto_node(void *blob, int sec_rev); |
64 | #else | 64 | #else |
65 | static inline void fdt_fixup_crypto_node(void *blob, int sec_rev) {} | 65 | static inline void fdt_fixup_crypto_node(void *blob, int sec_rev) {} |
66 | #endif | 66 | #endif |
67 | 67 | ||
68 | #ifdef CONFIG_PCI | 68 | #ifdef CONFIG_PCI |
69 | #include <pci.h> | 69 | #include <pci.h> |
70 | int fdt_pci_dma_ranges(void *blob, int phb_off, struct pci_controller *hose); | 70 | int fdt_pci_dma_ranges(void *blob, int phb_off, struct pci_controller *hose); |
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | #ifdef CONFIG_OF_BOARD_SETUP | 73 | #ifdef CONFIG_OF_BOARD_SETUP |
74 | void ft_board_setup(void *blob, bd_t *bd); | 74 | void ft_board_setup(void *blob, bd_t *bd); |
75 | void ft_cpu_setup(void *blob, bd_t *bd); | 75 | void ft_cpu_setup(void *blob, bd_t *bd); |
76 | void ft_pci_setup(void *blob, bd_t *bd); | 76 | void ft_pci_setup(void *blob, bd_t *bd); |
77 | #endif | 77 | #endif |
78 | 78 | ||
79 | void set_working_fdt_addr(void *addr); | 79 | void set_working_fdt_addr(void *addr); |
80 | int fdt_resize(void *blob); | 80 | int fdt_resize(void *blob); |
81 | 81 | ||
82 | int fdt_fixup_nor_flash_size(void *blob, int cs, u32 size); | 82 | int fdt_fixup_nor_flash_size(void *blob, int cs, u32 size); |
83 | 83 | ||
84 | void fdt_fixup_mtdparts(void *fdt, void *node_info, int node_info_size); | 84 | void fdt_fixup_mtdparts(void *fdt, void *node_info, int node_info_size); |
85 | void fdt_del_node_and_alias(void *blob, const char *alias); | ||
85 | 86 | ||
86 | #endif /* ifdef CONFIG_OF_LIBFDT */ | 87 | #endif /* ifdef CONFIG_OF_LIBFDT */ |
87 | #endif /* ifndef __FDT_SUPPORT_H */ | 88 | #endif /* ifndef __FDT_SUPPORT_H */ |
88 | 89 |