]>
Commit | Line | Data |
---|---|---|
64dbbd40 GVB |
1 | /* |
2 | * (C) Copyright 2007 | |
3 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
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 | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
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 | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | ||
24 | #include <common.h> | |
25 | #include <linux/ctype.h> | |
26 | #include <linux/types.h> | |
64dbbd40 GVB |
27 | #include <asm/global_data.h> |
28 | #include <fdt.h> | |
29 | #include <libfdt.h> | |
30 | #include <fdt_support.h> | |
151c8b09 | 31 | #include <exports.h> |
64dbbd40 GVB |
32 | |
33 | /* | |
34 | * Global data (for the gd->bd) | |
35 | */ | |
36 | DECLARE_GLOBAL_DATA_PTR; | |
37 | ||
bb930e76 GVB |
38 | /* |
39 | * fdt points to our working device tree. | |
40 | */ | |
41 | struct fdt_header *fdt; | |
42 | ||
64dbbd40 GVB |
43 | /********************************************************************/ |
44 | ||
a3c2933e KG |
45 | /** |
46 | * fdt_find_and_setprop: Find a node and set it's property | |
47 | * | |
48 | * @fdt: ptr to device tree | |
49 | * @node: path of node | |
50 | * @prop: property name | |
51 | * @val: ptr to new value | |
52 | * @len: length of new property value | |
53 | * @create: flag to create the property if it doesn't exist | |
54 | * | |
55 | * Convenience function to directly set a property given the path to the node. | |
56 | */ | |
57 | int fdt_find_and_setprop(void *fdt, const char *node, const char *prop, | |
58 | const void *val, int len, int create) | |
59 | { | |
8d04f02f | 60 | int nodeoff = fdt_path_offset(fdt, node); |
a3c2933e KG |
61 | |
62 | if (nodeoff < 0) | |
63 | return nodeoff; | |
64 | ||
65 | if ((!create) && (fdt_get_property(fdt, nodeoff, prop, 0) == NULL)) | |
66 | return 0; /* create flag not set; so exit quietly */ | |
67 | ||
68 | return fdt_setprop(fdt, nodeoff, prop, val, len); | |
69 | } | |
70 | ||
151c8b09 KG |
71 | #ifdef CONFIG_OF_STDOUT_VIA_ALIAS |
72 | static int fdt_fixup_stdout(void *fdt, int choosenoff) | |
73 | { | |
74 | int err = 0; | |
75 | #ifdef CONFIG_CONS_INDEX | |
76 | int node; | |
77 | char sername[9] = { 0 }; | |
78 | const char *path; | |
79 | ||
80 | sprintf(sername, "serial%d", CONFIG_CONS_INDEX - 1); | |
81 | ||
82 | err = node = fdt_path_offset(fdt, "/aliases"); | |
83 | if (node >= 0) { | |
84 | int len; | |
85 | path = fdt_getprop(fdt, node, sername, &len); | |
86 | if (path) { | |
87 | char *p = malloc(len); | |
88 | err = -FDT_ERR_NOSPACE; | |
89 | if (p) { | |
90 | memcpy(p, path, len); | |
91 | err = fdt_setprop(fdt, choosenoff, | |
92 | "linux,stdout-path", p, len); | |
93 | free(p); | |
94 | } | |
95 | } else { | |
96 | err = len; | |
97 | } | |
98 | } | |
99 | #endif | |
100 | if (err < 0) | |
101 | printf("WARNING: could not set linux,stdout-path %s.\n", | |
102 | fdt_strerror(err)); | |
103 | ||
104 | return err; | |
105 | } | |
106 | #endif | |
107 | ||
64dbbd40 GVB |
108 | int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force) |
109 | { | |
64dbbd40 GVB |
110 | int nodeoffset; |
111 | int err; | |
35ec398f GVB |
112 | u32 tmp; /* used to set 32 bit integer properties */ |
113 | char *str; /* used to set string properties */ | |
b60af3d4 | 114 | const char *path; |
64dbbd40 GVB |
115 | |
116 | err = fdt_check_header(fdt); | |
117 | if (err < 0) { | |
5fe6be62 | 118 | printf("fdt_chosen: %s\n", fdt_strerror(err)); |
64dbbd40 GVB |
119 | return err; |
120 | } | |
121 | ||
64dbbd40 | 122 | if (initrd_start && initrd_end) { |
8d04f02f KG |
123 | uint64_t addr, size; |
124 | int total = fdt_num_mem_rsv(fdt); | |
c28abb9c GVB |
125 | int j; |
126 | ||
c28abb9c GVB |
127 | /* |
128 | * Look for an existing entry and update it. If we don't find | |
129 | * the entry, we will j be the next available slot. | |
130 | */ | |
8d04f02f KG |
131 | for (j = 0; j < total; j++) { |
132 | err = fdt_get_mem_rsv(fdt, j, &addr, &size); | |
133 | if (addr == initrd_start) { | |
134 | fdt_del_mem_rsv(fdt, j); | |
c28abb9c GVB |
135 | break; |
136 | } | |
137 | } | |
8d04f02f KG |
138 | |
139 | err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start + 1); | |
64dbbd40 | 140 | if (err < 0) { |
5fe6be62 | 141 | printf("fdt_chosen: %s\n", fdt_strerror(err)); |
64dbbd40 GVB |
142 | return err; |
143 | } | |
144 | } | |
145 | ||
146 | /* | |
147 | * Find the "chosen" node. | |
148 | */ | |
8d04f02f | 149 | nodeoffset = fdt_path_offset (fdt, "/chosen"); |
64dbbd40 GVB |
150 | |
151 | /* | |
b60af3d4 | 152 | * If there is no "chosen" node in the blob, create it. |
64dbbd40 GVB |
153 | */ |
154 | if (nodeoffset < 0) { | |
155 | /* | |
156 | * Create a new node "/chosen" (offset 0 is root level) | |
157 | */ | |
158 | nodeoffset = fdt_add_subnode(fdt, 0, "chosen"); | |
159 | if (nodeoffset < 0) { | |
5fe6be62 | 160 | printf("WARNING: could not create /chosen %s.\n", |
35ec398f | 161 | fdt_strerror(nodeoffset)); |
64dbbd40 GVB |
162 | return nodeoffset; |
163 | } | |
164 | } | |
165 | ||
166 | /* | |
b60af3d4 GVB |
167 | * Create /chosen properites that don't exist in the fdt. |
168 | * If the property exists, update it only if the "force" parameter | |
169 | * is true. | |
64dbbd40 GVB |
170 | */ |
171 | str = getenv("bootargs"); | |
172 | if (str != NULL) { | |
b60af3d4 GVB |
173 | path = fdt_getprop(fdt, nodeoffset, "bootargs", NULL); |
174 | if ((path == NULL) || force) { | |
175 | err = fdt_setprop(fdt, nodeoffset, | |
176 | "bootargs", str, strlen(str)+1); | |
177 | if (err < 0) | |
178 | printf("WARNING: could not set bootargs %s.\n", | |
179 | fdt_strerror(err)); | |
180 | } | |
64dbbd40 GVB |
181 | } |
182 | if (initrd_start && initrd_end) { | |
b60af3d4 GVB |
183 | path = fdt_getprop(fdt, nodeoffset, "linux,initrd-start", NULL); |
184 | if ((path == NULL) || force) { | |
185 | tmp = __cpu_to_be32(initrd_start); | |
186 | err = fdt_setprop(fdt, nodeoffset, | |
187 | "linux,initrd-start", &tmp, sizeof(tmp)); | |
188 | if (err < 0) | |
189 | printf("WARNING: " | |
190 | "could not set linux,initrd-start %s.\n", | |
191 | fdt_strerror(err)); | |
192 | tmp = __cpu_to_be32(initrd_end); | |
193 | err = fdt_setprop(fdt, nodeoffset, | |
194 | "linux,initrd-end", &tmp, sizeof(tmp)); | |
195 | if (err < 0) | |
196 | printf("WARNING: could not set linux,initrd-end %s.\n", | |
197 | fdt_strerror(err)); | |
198 | } | |
64dbbd40 | 199 | } |
151c8b09 KG |
200 | |
201 | #ifdef CONFIG_OF_STDOUT_VIA_ALIAS | |
b60af3d4 GVB |
202 | path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL); |
203 | if ((path == NULL) || force) | |
204 | err = fdt_fixup_stdout(fdt, nodeoffset); | |
151c8b09 KG |
205 | #endif |
206 | ||
64dbbd40 | 207 | #ifdef OF_STDOUT_PATH |
b60af3d4 GVB |
208 | path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL); |
209 | if ((path == NULL) || force) { | |
210 | err = fdt_setprop(fdt, nodeoffset, | |
211 | "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1); | |
212 | if (err < 0) | |
213 | printf("WARNING: could not set linux,stdout-path %s.\n", | |
214 | fdt_strerror(err)); | |
215 | } | |
64dbbd40 GVB |
216 | #endif |
217 | ||
64dbbd40 GVB |
218 | return err; |
219 | } | |
220 | ||
221 | /********************************************************************/ | |
222 | ||
223 | #ifdef CONFIG_OF_HAS_UBOOT_ENV | |
224 | ||
225 | /* Function that returns a character from the environment */ | |
226 | extern uchar(*env_get_char) (int); | |
227 | ||
228 | ||
229 | int fdt_env(void *fdt) | |
230 | { | |
231 | int nodeoffset; | |
232 | int err; | |
233 | int k, nxt; | |
234 | int i; | |
235 | static char tmpenv[256]; | |
236 | ||
237 | err = fdt_check_header(fdt); | |
238 | if (err < 0) { | |
5fe6be62 | 239 | printf("fdt_env: %s\n", fdt_strerror(err)); |
64dbbd40 GVB |
240 | return err; |
241 | } | |
242 | ||
243 | /* | |
244 | * See if we already have a "u-boot-env" node, delete it if so. | |
245 | * Then create a new empty node. | |
246 | */ | |
8d04f02f | 247 | nodeoffset = fdt_path_offset (fdt, "/u-boot-env"); |
64dbbd40 GVB |
248 | if (nodeoffset >= 0) { |
249 | err = fdt_del_node(fdt, nodeoffset); | |
250 | if (err < 0) { | |
5fe6be62 | 251 | printf("fdt_env: %s\n", fdt_strerror(err)); |
64dbbd40 GVB |
252 | return err; |
253 | } | |
254 | } | |
255 | /* | |
256 | * Create a new node "/u-boot-env" (offset 0 is root level) | |
257 | */ | |
258 | nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env"); | |
259 | if (nodeoffset < 0) { | |
5fe6be62 | 260 | printf("WARNING: could not create /u-boot-env %s.\n", |
35ec398f | 261 | fdt_strerror(nodeoffset)); |
64dbbd40 GVB |
262 | return nodeoffset; |
263 | } | |
264 | ||
265 | for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { | |
266 | char *s, *lval, *rval; | |
267 | ||
268 | /* | |
269 | * Find the end of the name=definition | |
270 | */ | |
271 | for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) | |
272 | ; | |
273 | s = tmpenv; | |
274 | for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k) | |
275 | *s++ = env_get_char(k); | |
276 | *s++ = '\0'; | |
277 | lval = tmpenv; | |
278 | /* | |
279 | * Find the first '=': it separates the name from the value | |
280 | */ | |
281 | s = strchr(tmpenv, '='); | |
282 | if (s != NULL) { | |
283 | *s++ = '\0'; | |
284 | rval = s; | |
285 | } else | |
286 | continue; | |
287 | err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1); | |
288 | if (err < 0) { | |
5fe6be62 | 289 | printf("WARNING: could not set %s %s.\n", |
35ec398f | 290 | lval, fdt_strerror(err)); |
64dbbd40 GVB |
291 | return err; |
292 | } | |
293 | } | |
294 | return 0; | |
295 | } | |
c28abb9c | 296 | #endif /* ifdef CONFIG_OF_HAS_UBOOT_ENV */ |
64dbbd40 GVB |
297 | |
298 | /********************************************************************/ | |
299 | ||
300 | #ifdef CONFIG_OF_HAS_BD_T | |
301 | ||
302 | #define BDM(x) { .name = #x, .offset = offsetof(bd_t, bi_ ##x ) } | |
303 | ||
304 | static const struct { | |
305 | const char *name; | |
306 | int offset; | |
307 | } bd_map[] = { | |
308 | BDM(memstart), | |
309 | BDM(memsize), | |
310 | BDM(flashstart), | |
311 | BDM(flashsize), | |
312 | BDM(flashoffset), | |
313 | BDM(sramstart), | |
314 | BDM(sramsize), | |
315 | #if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \ | |
316 | || defined(CONFIG_E500) | |
317 | BDM(immr_base), | |
318 | #endif | |
319 | #if defined(CONFIG_MPC5xxx) | |
320 | BDM(mbar_base), | |
321 | #endif | |
322 | #if defined(CONFIG_MPC83XX) | |
323 | BDM(immrbar), | |
324 | #endif | |
325 | #if defined(CONFIG_MPC8220) | |
326 | BDM(mbar_base), | |
327 | BDM(inpfreq), | |
328 | BDM(pcifreq), | |
329 | BDM(pevfreq), | |
330 | BDM(flbfreq), | |
331 | BDM(vcofreq), | |
332 | #endif | |
333 | BDM(bootflags), | |
334 | BDM(ip_addr), | |
335 | BDM(intfreq), | |
336 | BDM(busfreq), | |
337 | #ifdef CONFIG_CPM2 | |
338 | BDM(cpmfreq), | |
339 | BDM(brgfreq), | |
340 | BDM(sccfreq), | |
341 | BDM(vco), | |
342 | #endif | |
343 | #if defined(CONFIG_MPC5xxx) | |
344 | BDM(ipbfreq), | |
345 | BDM(pcifreq), | |
346 | #endif | |
347 | BDM(baudrate), | |
348 | }; | |
349 | ||
350 | ||
351 | int fdt_bd_t(void *fdt) | |
352 | { | |
353 | bd_t *bd = gd->bd; | |
354 | int nodeoffset; | |
355 | int err; | |
35ec398f | 356 | u32 tmp; /* used to set 32 bit integer properties */ |
64dbbd40 GVB |
357 | int i; |
358 | ||
359 | err = fdt_check_header(fdt); | |
360 | if (err < 0) { | |
5fe6be62 | 361 | printf("fdt_bd_t: %s\n", fdt_strerror(err)); |
64dbbd40 GVB |
362 | return err; |
363 | } | |
364 | ||
365 | /* | |
366 | * See if we already have a "bd_t" node, delete it if so. | |
367 | * Then create a new empty node. | |
368 | */ | |
8d04f02f | 369 | nodeoffset = fdt_path_offset (fdt, "/bd_t"); |
64dbbd40 GVB |
370 | if (nodeoffset >= 0) { |
371 | err = fdt_del_node(fdt, nodeoffset); | |
372 | if (err < 0) { | |
5fe6be62 | 373 | printf("fdt_bd_t: %s\n", fdt_strerror(err)); |
64dbbd40 GVB |
374 | return err; |
375 | } | |
376 | } | |
377 | /* | |
378 | * Create a new node "/bd_t" (offset 0 is root level) | |
379 | */ | |
380 | nodeoffset = fdt_add_subnode(fdt, 0, "bd_t"); | |
381 | if (nodeoffset < 0) { | |
5fe6be62 | 382 | printf("WARNING: could not create /bd_t %s.\n", |
35ec398f | 383 | fdt_strerror(nodeoffset)); |
5fe6be62 | 384 | printf("fdt_bd_t: %s\n", fdt_strerror(nodeoffset)); |
64dbbd40 GVB |
385 | return nodeoffset; |
386 | } | |
387 | /* | |
388 | * Use the string/pointer structure to create the entries... | |
389 | */ | |
390 | for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) { | |
391 | tmp = cpu_to_be32(getenv("bootargs")); | |
35ec398f GVB |
392 | err = fdt_setprop(fdt, nodeoffset, |
393 | bd_map[i].name, &tmp, sizeof(tmp)); | |
64dbbd40 | 394 | if (err < 0) |
5fe6be62 | 395 | printf("WARNING: could not set %s %s.\n", |
35ec398f | 396 | bd_map[i].name, fdt_strerror(err)); |
64dbbd40 GVB |
397 | } |
398 | /* | |
399 | * Add a couple of oddball entries... | |
400 | */ | |
401 | err = fdt_setprop(fdt, nodeoffset, "enetaddr", &bd->bi_enetaddr, 6); | |
402 | if (err < 0) | |
5fe6be62 | 403 | printf("WARNING: could not set enetaddr %s.\n", |
35ec398f | 404 | fdt_strerror(err)); |
64dbbd40 GVB |
405 | err = fdt_setprop(fdt, nodeoffset, "ethspeed", &bd->bi_ethspeed, 4); |
406 | if (err < 0) | |
5fe6be62 | 407 | printf("WARNING: could not set ethspeed %s.\n", |
35ec398f | 408 | fdt_strerror(err)); |
64dbbd40 GVB |
409 | return 0; |
410 | } | |
c28abb9c | 411 | #endif /* ifdef CONFIG_OF_HAS_BD_T */ |
64dbbd40 | 412 | |
e93becf8 KG |
413 | void do_fixup_by_path(void *fdt, const char *path, const char *prop, |
414 | const void *val, int len, int create) | |
415 | { | |
416 | #if defined(DEBUG) | |
417 | int i; | |
d9ad115b | 418 | debug("Updating property '%s/%s' = ", path, prop); |
e93becf8 KG |
419 | for (i = 0; i < len; i++) |
420 | debug(" %.2x", *(u8*)(val+i)); | |
421 | debug("\n"); | |
422 | #endif | |
423 | int rc = fdt_find_and_setprop(fdt, path, prop, val, len, create); | |
424 | if (rc) | |
425 | printf("Unable to update property %s:%s, err=%s\n", | |
426 | path, prop, fdt_strerror(rc)); | |
427 | } | |
428 | ||
429 | void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop, | |
430 | u32 val, int create) | |
431 | { | |
432 | val = cpu_to_fdt32(val); | |
433 | do_fixup_by_path(fdt, path, prop, &val, sizeof(val), create); | |
434 | } | |
435 | ||
9eb77cea KG |
436 | void do_fixup_by_prop(void *fdt, |
437 | const char *pname, const void *pval, int plen, | |
438 | const char *prop, const void *val, int len, | |
439 | int create) | |
440 | { | |
441 | int off; | |
442 | #if defined(DEBUG) | |
443 | int i; | |
d9ad115b | 444 | debug("Updating property '%s' = ", prop); |
9eb77cea KG |
445 | for (i = 0; i < len; i++) |
446 | debug(" %.2x", *(u8*)(val+i)); | |
447 | debug("\n"); | |
448 | #endif | |
449 | off = fdt_node_offset_by_prop_value(fdt, -1, pname, pval, plen); | |
450 | while (off != -FDT_ERR_NOTFOUND) { | |
451 | if (create || (fdt_get_property(fdt, off, prop, 0) != NULL)) | |
452 | fdt_setprop(fdt, off, prop, val, len); | |
453 | off = fdt_node_offset_by_prop_value(fdt, off, pname, pval, plen); | |
454 | } | |
455 | } | |
456 | ||
457 | void do_fixup_by_prop_u32(void *fdt, | |
458 | const char *pname, const void *pval, int plen, | |
459 | const char *prop, u32 val, int create) | |
460 | { | |
461 | val = cpu_to_fdt32(val); | |
462 | do_fixup_by_prop(fdt, pname, pval, plen, prop, &val, 4, create); | |
463 | } | |
464 | ||
465 | void do_fixup_by_compat(void *fdt, const char *compat, | |
466 | const char *prop, const void *val, int len, int create) | |
467 | { | |
468 | int off = -1; | |
469 | #if defined(DEBUG) | |
470 | int i; | |
d9ad115b | 471 | debug("Updating property '%s' = ", prop); |
9eb77cea KG |
472 | for (i = 0; i < len; i++) |
473 | debug(" %.2x", *(u8*)(val+i)); | |
474 | debug("\n"); | |
475 | #endif | |
476 | off = fdt_node_offset_by_compatible(fdt, -1, compat); | |
477 | while (off != -FDT_ERR_NOTFOUND) { | |
478 | if (create || (fdt_get_property(fdt, off, prop, 0) != NULL)) | |
479 | fdt_setprop(fdt, off, prop, val, len); | |
480 | off = fdt_node_offset_by_compatible(fdt, off, compat); | |
481 | } | |
482 | } | |
483 | ||
484 | void do_fixup_by_compat_u32(void *fdt, const char *compat, | |
485 | const char *prop, u32 val, int create) | |
486 | { | |
487 | val = cpu_to_fdt32(val); | |
488 | do_fixup_by_compat(fdt, compat, prop, &val, 4, create); | |
489 | } | |
490 | ||
3c927281 KG |
491 | int fdt_fixup_memory(void *blob, u64 start, u64 size) |
492 | { | |
493 | int err, nodeoffset, len = 0; | |
494 | u8 tmp[16]; | |
495 | const u32 *addrcell, *sizecell; | |
496 | ||
497 | err = fdt_check_header(blob); | |
498 | if (err < 0) { | |
499 | printf("%s: %s\n", __FUNCTION__, fdt_strerror(err)); | |
500 | return err; | |
501 | } | |
502 | ||
503 | /* update, or add and update /memory node */ | |
504 | nodeoffset = fdt_path_offset(blob, "/memory"); | |
505 | if (nodeoffset < 0) { | |
506 | nodeoffset = fdt_add_subnode(blob, 0, "memory"); | |
507 | if (nodeoffset < 0) | |
508 | printf("WARNING: could not create /memory: %s.\n", | |
509 | fdt_strerror(nodeoffset)); | |
510 | return nodeoffset; | |
511 | } | |
512 | err = fdt_setprop(blob, nodeoffset, "device_type", "memory", | |
513 | sizeof("memory")); | |
514 | if (err < 0) { | |
515 | printf("WARNING: could not set %s %s.\n", "device_type", | |
516 | fdt_strerror(err)); | |
517 | return err; | |
518 | } | |
519 | ||
520 | addrcell = fdt_getprop(blob, 0, "#address-cells", NULL); | |
521 | /* use shifts and mask to ensure endianness */ | |
522 | if ((addrcell) && (*addrcell == 2)) { | |
523 | tmp[0] = (start >> 56) & 0xff; | |
524 | tmp[1] = (start >> 48) & 0xff; | |
525 | tmp[2] = (start >> 40) & 0xff; | |
526 | tmp[3] = (start >> 32) & 0xff; | |
527 | tmp[4] = (start >> 24) & 0xff; | |
528 | tmp[5] = (start >> 16) & 0xff; | |
529 | tmp[6] = (start >> 8) & 0xff; | |
530 | tmp[7] = (start ) & 0xff; | |
531 | len = 8; | |
532 | } else { | |
533 | tmp[0] = (start >> 24) & 0xff; | |
534 | tmp[1] = (start >> 16) & 0xff; | |
535 | tmp[2] = (start >> 8) & 0xff; | |
536 | tmp[3] = (start ) & 0xff; | |
537 | len = 4; | |
538 | } | |
539 | ||
540 | sizecell = fdt_getprop(blob, 0, "#size-cells", NULL); | |
541 | /* use shifts and mask to ensure endianness */ | |
542 | if ((sizecell) && (*sizecell == 2)) { | |
543 | tmp[0+len] = (size >> 56) & 0xff; | |
544 | tmp[1+len] = (size >> 48) & 0xff; | |
545 | tmp[2+len] = (size >> 40) & 0xff; | |
546 | tmp[3+len] = (size >> 32) & 0xff; | |
547 | tmp[4+len] = (size >> 24) & 0xff; | |
548 | tmp[5+len] = (size >> 16) & 0xff; | |
549 | tmp[6+len] = (size >> 8) & 0xff; | |
550 | tmp[7+len] = (size ) & 0xff; | |
551 | len += 8; | |
552 | } else { | |
553 | tmp[0+len] = (size >> 24) & 0xff; | |
554 | tmp[1+len] = (size >> 16) & 0xff; | |
555 | tmp[2+len] = (size >> 8) & 0xff; | |
556 | tmp[3+len] = (size ) & 0xff; | |
557 | len += 4; | |
558 | } | |
559 | ||
560 | err = fdt_setprop(blob, nodeoffset, "reg", tmp, len); | |
561 | if (err < 0) { | |
562 | printf("WARNING: could not set %s %s.\n", | |
563 | "reg", fdt_strerror(err)); | |
564 | return err; | |
565 | } | |
566 | return 0; | |
567 | } | |
568 | ||
c01b17dd GVB |
569 | #if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) ||\ |
570 | defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3) | |
571 | ||
ab544633 KG |
572 | void fdt_fixup_ethernet(void *fdt, bd_t *bd) |
573 | { | |
574 | int node; | |
575 | const char *path; | |
576 | ||
577 | node = fdt_path_offset(fdt, "/aliases"); | |
578 | if (node >= 0) { | |
579 | #if defined(CONFIG_HAS_ETH0) | |
580 | path = fdt_getprop(fdt, node, "ethernet0", NULL); | |
581 | if (path) { | |
582 | do_fixup_by_path(fdt, path, "mac-address", | |
583 | bd->bi_enetaddr, 6, 0); | |
584 | do_fixup_by_path(fdt, path, "local-mac-address", | |
585 | bd->bi_enetaddr, 6, 1); | |
586 | } | |
587 | #endif | |
588 | #if defined(CONFIG_HAS_ETH1) | |
589 | path = fdt_getprop(fdt, node, "ethernet1", NULL); | |
590 | if (path) { | |
591 | do_fixup_by_path(fdt, path, "mac-address", | |
592 | bd->bi_enet1addr, 6, 0); | |
593 | do_fixup_by_path(fdt, path, "local-mac-address", | |
594 | bd->bi_enet1addr, 6, 1); | |
595 | } | |
596 | #endif | |
597 | #if defined(CONFIG_HAS_ETH2) | |
598 | path = fdt_getprop(fdt, node, "ethernet2", NULL); | |
599 | if (path) { | |
600 | do_fixup_by_path(fdt, path, "mac-address", | |
601 | bd->bi_enet2addr, 6, 0); | |
602 | do_fixup_by_path(fdt, path, "local-mac-address", | |
603 | bd->bi_enet2addr, 6, 1); | |
604 | } | |
605 | #endif | |
606 | #if defined(CONFIG_HAS_ETH3) | |
607 | path = fdt_getprop(fdt, node, "ethernet3", NULL); | |
608 | if (path) { | |
609 | do_fixup_by_path(fdt, path, "mac-address", | |
610 | bd->bi_enet3addr, 6, 0); | |
611 | do_fixup_by_path(fdt, path, "local-mac-address", | |
612 | bd->bi_enet3addr, 6, 1); | |
613 | } | |
614 | #endif | |
615 | } | |
616 | } | |
c01b17dd | 617 | #endif |