]>
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 */ | |
64dbbd40 GVB |
114 | |
115 | err = fdt_check_header(fdt); | |
116 | if (err < 0) { | |
5fe6be62 | 117 | printf("fdt_chosen: %s\n", fdt_strerror(err)); |
64dbbd40 GVB |
118 | return err; |
119 | } | |
120 | ||
64dbbd40 | 121 | if (initrd_start && initrd_end) { |
8d04f02f KG |
122 | uint64_t addr, size; |
123 | int total = fdt_num_mem_rsv(fdt); | |
c28abb9c GVB |
124 | int j; |
125 | ||
c28abb9c GVB |
126 | /* |
127 | * Look for an existing entry and update it. If we don't find | |
128 | * the entry, we will j be the next available slot. | |
129 | */ | |
8d04f02f KG |
130 | for (j = 0; j < total; j++) { |
131 | err = fdt_get_mem_rsv(fdt, j, &addr, &size); | |
132 | if (addr == initrd_start) { | |
133 | fdt_del_mem_rsv(fdt, j); | |
c28abb9c GVB |
134 | break; |
135 | } | |
136 | } | |
8d04f02f KG |
137 | |
138 | err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start + 1); | |
64dbbd40 | 139 | if (err < 0) { |
5fe6be62 | 140 | printf("fdt_chosen: %s\n", fdt_strerror(err)); |
64dbbd40 GVB |
141 | return err; |
142 | } | |
143 | } | |
144 | ||
145 | /* | |
146 | * Find the "chosen" node. | |
147 | */ | |
8d04f02f | 148 | nodeoffset = fdt_path_offset (fdt, "/chosen"); |
64dbbd40 GVB |
149 | |
150 | /* | |
151 | * If we have a "chosen" node already the "force the writing" | |
152 | * is not set, our job is done. | |
153 | */ | |
154 | if ((nodeoffset >= 0) && !force) | |
155 | return 0; | |
156 | ||
157 | /* | |
158 | * No "chosen" node in the blob: create it. | |
159 | */ | |
160 | if (nodeoffset < 0) { | |
161 | /* | |
162 | * Create a new node "/chosen" (offset 0 is root level) | |
163 | */ | |
164 | nodeoffset = fdt_add_subnode(fdt, 0, "chosen"); | |
165 | if (nodeoffset < 0) { | |
5fe6be62 | 166 | printf("WARNING: could not create /chosen %s.\n", |
35ec398f | 167 | fdt_strerror(nodeoffset)); |
64dbbd40 GVB |
168 | return nodeoffset; |
169 | } | |
170 | } | |
171 | ||
172 | /* | |
173 | * Update pre-existing properties, create them if non-existant. | |
174 | */ | |
175 | str = getenv("bootargs"); | |
176 | if (str != NULL) { | |
35ec398f GVB |
177 | err = fdt_setprop(fdt, nodeoffset, |
178 | "bootargs", str, strlen(str)+1); | |
64dbbd40 | 179 | if (err < 0) |
5fe6be62 | 180 | printf("WARNING: could not set bootargs %s.\n", |
35ec398f | 181 | fdt_strerror(err)); |
64dbbd40 GVB |
182 | } |
183 | if (initrd_start && initrd_end) { | |
184 | tmp = __cpu_to_be32(initrd_start); | |
35ec398f GVB |
185 | err = fdt_setprop(fdt, nodeoffset, |
186 | "linux,initrd-start", &tmp, sizeof(tmp)); | |
64dbbd40 | 187 | if (err < 0) |
5fe6be62 GVB |
188 | printf("WARNING: " |
189 | "could not set linux,initrd-start %s.\n", | |
35ec398f | 190 | fdt_strerror(err)); |
64dbbd40 | 191 | tmp = __cpu_to_be32(initrd_end); |
35ec398f GVB |
192 | err = fdt_setprop(fdt, nodeoffset, |
193 | "linux,initrd-end", &tmp, sizeof(tmp)); | |
64dbbd40 | 194 | if (err < 0) |
5fe6be62 | 195 | printf("WARNING: could not set linux,initrd-end %s.\n", |
35ec398f | 196 | fdt_strerror(err)); |
64dbbd40 | 197 | } |
151c8b09 KG |
198 | |
199 | #ifdef CONFIG_OF_STDOUT_VIA_ALIAS | |
200 | err = fdt_fixup_stdout(fdt, nodeoffset); | |
201 | #endif | |
202 | ||
64dbbd40 | 203 | #ifdef OF_STDOUT_PATH |
35ec398f GVB |
204 | err = fdt_setprop(fdt, nodeoffset, |
205 | "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1); | |
64dbbd40 | 206 | if (err < 0) |
5fe6be62 | 207 | printf("WARNING: could not set linux,stdout-path %s.\n", |
35ec398f | 208 | fdt_strerror(err)); |
64dbbd40 GVB |
209 | #endif |
210 | ||
64dbbd40 GVB |
211 | return err; |
212 | } | |
213 | ||
214 | /********************************************************************/ | |
215 | ||
216 | #ifdef CONFIG_OF_HAS_UBOOT_ENV | |
217 | ||
218 | /* Function that returns a character from the environment */ | |
219 | extern uchar(*env_get_char) (int); | |
220 | ||
221 | ||
222 | int fdt_env(void *fdt) | |
223 | { | |
224 | int nodeoffset; | |
225 | int err; | |
226 | int k, nxt; | |
227 | int i; | |
228 | static char tmpenv[256]; | |
229 | ||
230 | err = fdt_check_header(fdt); | |
231 | if (err < 0) { | |
5fe6be62 | 232 | printf("fdt_env: %s\n", fdt_strerror(err)); |
64dbbd40 GVB |
233 | return err; |
234 | } | |
235 | ||
236 | /* | |
237 | * See if we already have a "u-boot-env" node, delete it if so. | |
238 | * Then create a new empty node. | |
239 | */ | |
8d04f02f | 240 | nodeoffset = fdt_path_offset (fdt, "/u-boot-env"); |
64dbbd40 GVB |
241 | if (nodeoffset >= 0) { |
242 | err = fdt_del_node(fdt, nodeoffset); | |
243 | if (err < 0) { | |
5fe6be62 | 244 | printf("fdt_env: %s\n", fdt_strerror(err)); |
64dbbd40 GVB |
245 | return err; |
246 | } | |
247 | } | |
248 | /* | |
249 | * Create a new node "/u-boot-env" (offset 0 is root level) | |
250 | */ | |
251 | nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env"); | |
252 | if (nodeoffset < 0) { | |
5fe6be62 | 253 | printf("WARNING: could not create /u-boot-env %s.\n", |
35ec398f | 254 | fdt_strerror(nodeoffset)); |
64dbbd40 GVB |
255 | return nodeoffset; |
256 | } | |
257 | ||
258 | for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { | |
259 | char *s, *lval, *rval; | |
260 | ||
261 | /* | |
262 | * Find the end of the name=definition | |
263 | */ | |
264 | for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) | |
265 | ; | |
266 | s = tmpenv; | |
267 | for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k) | |
268 | *s++ = env_get_char(k); | |
269 | *s++ = '\0'; | |
270 | lval = tmpenv; | |
271 | /* | |
272 | * Find the first '=': it separates the name from the value | |
273 | */ | |
274 | s = strchr(tmpenv, '='); | |
275 | if (s != NULL) { | |
276 | *s++ = '\0'; | |
277 | rval = s; | |
278 | } else | |
279 | continue; | |
280 | err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1); | |
281 | if (err < 0) { | |
5fe6be62 | 282 | printf("WARNING: could not set %s %s.\n", |
35ec398f | 283 | lval, fdt_strerror(err)); |
64dbbd40 GVB |
284 | return err; |
285 | } | |
286 | } | |
287 | return 0; | |
288 | } | |
c28abb9c | 289 | #endif /* ifdef CONFIG_OF_HAS_UBOOT_ENV */ |
64dbbd40 GVB |
290 | |
291 | /********************************************************************/ | |
292 | ||
293 | #ifdef CONFIG_OF_HAS_BD_T | |
294 | ||
295 | #define BDM(x) { .name = #x, .offset = offsetof(bd_t, bi_ ##x ) } | |
296 | ||
297 | static const struct { | |
298 | const char *name; | |
299 | int offset; | |
300 | } bd_map[] = { | |
301 | BDM(memstart), | |
302 | BDM(memsize), | |
303 | BDM(flashstart), | |
304 | BDM(flashsize), | |
305 | BDM(flashoffset), | |
306 | BDM(sramstart), | |
307 | BDM(sramsize), | |
308 | #if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \ | |
309 | || defined(CONFIG_E500) | |
310 | BDM(immr_base), | |
311 | #endif | |
312 | #if defined(CONFIG_MPC5xxx) | |
313 | BDM(mbar_base), | |
314 | #endif | |
315 | #if defined(CONFIG_MPC83XX) | |
316 | BDM(immrbar), | |
317 | #endif | |
318 | #if defined(CONFIG_MPC8220) | |
319 | BDM(mbar_base), | |
320 | BDM(inpfreq), | |
321 | BDM(pcifreq), | |
322 | BDM(pevfreq), | |
323 | BDM(flbfreq), | |
324 | BDM(vcofreq), | |
325 | #endif | |
326 | BDM(bootflags), | |
327 | BDM(ip_addr), | |
328 | BDM(intfreq), | |
329 | BDM(busfreq), | |
330 | #ifdef CONFIG_CPM2 | |
331 | BDM(cpmfreq), | |
332 | BDM(brgfreq), | |
333 | BDM(sccfreq), | |
334 | BDM(vco), | |
335 | #endif | |
336 | #if defined(CONFIG_MPC5xxx) | |
337 | BDM(ipbfreq), | |
338 | BDM(pcifreq), | |
339 | #endif | |
340 | BDM(baudrate), | |
341 | }; | |
342 | ||
343 | ||
344 | int fdt_bd_t(void *fdt) | |
345 | { | |
346 | bd_t *bd = gd->bd; | |
347 | int nodeoffset; | |
348 | int err; | |
35ec398f | 349 | u32 tmp; /* used to set 32 bit integer properties */ |
64dbbd40 GVB |
350 | int i; |
351 | ||
352 | err = fdt_check_header(fdt); | |
353 | if (err < 0) { | |
5fe6be62 | 354 | printf("fdt_bd_t: %s\n", fdt_strerror(err)); |
64dbbd40 GVB |
355 | return err; |
356 | } | |
357 | ||
358 | /* | |
359 | * See if we already have a "bd_t" node, delete it if so. | |
360 | * Then create a new empty node. | |
361 | */ | |
8d04f02f | 362 | nodeoffset = fdt_path_offset (fdt, "/bd_t"); |
64dbbd40 GVB |
363 | if (nodeoffset >= 0) { |
364 | err = fdt_del_node(fdt, nodeoffset); | |
365 | if (err < 0) { | |
5fe6be62 | 366 | printf("fdt_bd_t: %s\n", fdt_strerror(err)); |
64dbbd40 GVB |
367 | return err; |
368 | } | |
369 | } | |
370 | /* | |
371 | * Create a new node "/bd_t" (offset 0 is root level) | |
372 | */ | |
373 | nodeoffset = fdt_add_subnode(fdt, 0, "bd_t"); | |
374 | if (nodeoffset < 0) { | |
5fe6be62 | 375 | printf("WARNING: could not create /bd_t %s.\n", |
35ec398f | 376 | fdt_strerror(nodeoffset)); |
5fe6be62 | 377 | printf("fdt_bd_t: %s\n", fdt_strerror(nodeoffset)); |
64dbbd40 GVB |
378 | return nodeoffset; |
379 | } | |
380 | /* | |
381 | * Use the string/pointer structure to create the entries... | |
382 | */ | |
383 | for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) { | |
384 | tmp = cpu_to_be32(getenv("bootargs")); | |
35ec398f GVB |
385 | err = fdt_setprop(fdt, nodeoffset, |
386 | bd_map[i].name, &tmp, sizeof(tmp)); | |
64dbbd40 | 387 | if (err < 0) |
5fe6be62 | 388 | printf("WARNING: could not set %s %s.\n", |
35ec398f | 389 | bd_map[i].name, fdt_strerror(err)); |
64dbbd40 GVB |
390 | } |
391 | /* | |
392 | * Add a couple of oddball entries... | |
393 | */ | |
394 | err = fdt_setprop(fdt, nodeoffset, "enetaddr", &bd->bi_enetaddr, 6); | |
395 | if (err < 0) | |
5fe6be62 | 396 | printf("WARNING: could not set enetaddr %s.\n", |
35ec398f | 397 | fdt_strerror(err)); |
64dbbd40 GVB |
398 | err = fdt_setprop(fdt, nodeoffset, "ethspeed", &bd->bi_ethspeed, 4); |
399 | if (err < 0) | |
5fe6be62 | 400 | printf("WARNING: could not set ethspeed %s.\n", |
35ec398f | 401 | fdt_strerror(err)); |
64dbbd40 GVB |
402 | return 0; |
403 | } | |
c28abb9c | 404 | #endif /* ifdef CONFIG_OF_HAS_BD_T */ |
64dbbd40 | 405 | |
e93becf8 KG |
406 | void do_fixup_by_path(void *fdt, const char *path, const char *prop, |
407 | const void *val, int len, int create) | |
408 | { | |
409 | #if defined(DEBUG) | |
410 | int i; | |
411 | debug("Updating property '%s/%s' = ", node, prop); | |
412 | for (i = 0; i < len; i++) | |
413 | debug(" %.2x", *(u8*)(val+i)); | |
414 | debug("\n"); | |
415 | #endif | |
416 | int rc = fdt_find_and_setprop(fdt, path, prop, val, len, create); | |
417 | if (rc) | |
418 | printf("Unable to update property %s:%s, err=%s\n", | |
419 | path, prop, fdt_strerror(rc)); | |
420 | } | |
421 | ||
422 | void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop, | |
423 | u32 val, int create) | |
424 | { | |
425 | val = cpu_to_fdt32(val); | |
426 | do_fixup_by_path(fdt, path, prop, &val, sizeof(val), create); | |
427 | } | |
428 | ||
9eb77cea KG |
429 | void do_fixup_by_prop(void *fdt, |
430 | const char *pname, const void *pval, int plen, | |
431 | const char *prop, const void *val, int len, | |
432 | int create) | |
433 | { | |
434 | int off; | |
435 | #if defined(DEBUG) | |
436 | int i; | |
437 | debug("Updating property '%s/%s' = ", node, prop); | |
438 | for (i = 0; i < len; i++) | |
439 | debug(" %.2x", *(u8*)(val+i)); | |
440 | debug("\n"); | |
441 | #endif | |
442 | off = fdt_node_offset_by_prop_value(fdt, -1, pname, pval, plen); | |
443 | while (off != -FDT_ERR_NOTFOUND) { | |
444 | if (create || (fdt_get_property(fdt, off, prop, 0) != NULL)) | |
445 | fdt_setprop(fdt, off, prop, val, len); | |
446 | off = fdt_node_offset_by_prop_value(fdt, off, pname, pval, plen); | |
447 | } | |
448 | } | |
449 | ||
450 | void do_fixup_by_prop_u32(void *fdt, | |
451 | const char *pname, const void *pval, int plen, | |
452 | const char *prop, u32 val, int create) | |
453 | { | |
454 | val = cpu_to_fdt32(val); | |
455 | do_fixup_by_prop(fdt, pname, pval, plen, prop, &val, 4, create); | |
456 | } | |
457 | ||
458 | void do_fixup_by_compat(void *fdt, const char *compat, | |
459 | const char *prop, const void *val, int len, int create) | |
460 | { | |
461 | int off = -1; | |
462 | #if defined(DEBUG) | |
463 | int i; | |
464 | debug("Updating property '%s/%s' = ", node, prop); | |
465 | for (i = 0; i < len; i++) | |
466 | debug(" %.2x", *(u8*)(val+i)); | |
467 | debug("\n"); | |
468 | #endif | |
469 | off = fdt_node_offset_by_compatible(fdt, -1, compat); | |
470 | while (off != -FDT_ERR_NOTFOUND) { | |
471 | if (create || (fdt_get_property(fdt, off, prop, 0) != NULL)) | |
472 | fdt_setprop(fdt, off, prop, val, len); | |
473 | off = fdt_node_offset_by_compatible(fdt, off, compat); | |
474 | } | |
475 | } | |
476 | ||
477 | void do_fixup_by_compat_u32(void *fdt, const char *compat, | |
478 | const char *prop, u32 val, int create) | |
479 | { | |
480 | val = cpu_to_fdt32(val); | |
481 | do_fixup_by_compat(fdt, compat, prop, &val, 4, create); | |
482 | } | |
483 | ||
3c927281 KG |
484 | int fdt_fixup_memory(void *blob, u64 start, u64 size) |
485 | { | |
486 | int err, nodeoffset, len = 0; | |
487 | u8 tmp[16]; | |
488 | const u32 *addrcell, *sizecell; | |
489 | ||
490 | err = fdt_check_header(blob); | |
491 | if (err < 0) { | |
492 | printf("%s: %s\n", __FUNCTION__, fdt_strerror(err)); | |
493 | return err; | |
494 | } | |
495 | ||
496 | /* update, or add and update /memory node */ | |
497 | nodeoffset = fdt_path_offset(blob, "/memory"); | |
498 | if (nodeoffset < 0) { | |
499 | nodeoffset = fdt_add_subnode(blob, 0, "memory"); | |
500 | if (nodeoffset < 0) | |
501 | printf("WARNING: could not create /memory: %s.\n", | |
502 | fdt_strerror(nodeoffset)); | |
503 | return nodeoffset; | |
504 | } | |
505 | err = fdt_setprop(blob, nodeoffset, "device_type", "memory", | |
506 | sizeof("memory")); | |
507 | if (err < 0) { | |
508 | printf("WARNING: could not set %s %s.\n", "device_type", | |
509 | fdt_strerror(err)); | |
510 | return err; | |
511 | } | |
512 | ||
513 | addrcell = fdt_getprop(blob, 0, "#address-cells", NULL); | |
514 | /* use shifts and mask to ensure endianness */ | |
515 | if ((addrcell) && (*addrcell == 2)) { | |
516 | tmp[0] = (start >> 56) & 0xff; | |
517 | tmp[1] = (start >> 48) & 0xff; | |
518 | tmp[2] = (start >> 40) & 0xff; | |
519 | tmp[3] = (start >> 32) & 0xff; | |
520 | tmp[4] = (start >> 24) & 0xff; | |
521 | tmp[5] = (start >> 16) & 0xff; | |
522 | tmp[6] = (start >> 8) & 0xff; | |
523 | tmp[7] = (start ) & 0xff; | |
524 | len = 8; | |
525 | } else { | |
526 | tmp[0] = (start >> 24) & 0xff; | |
527 | tmp[1] = (start >> 16) & 0xff; | |
528 | tmp[2] = (start >> 8) & 0xff; | |
529 | tmp[3] = (start ) & 0xff; | |
530 | len = 4; | |
531 | } | |
532 | ||
533 | sizecell = fdt_getprop(blob, 0, "#size-cells", NULL); | |
534 | /* use shifts and mask to ensure endianness */ | |
535 | if ((sizecell) && (*sizecell == 2)) { | |
536 | tmp[0+len] = (size >> 56) & 0xff; | |
537 | tmp[1+len] = (size >> 48) & 0xff; | |
538 | tmp[2+len] = (size >> 40) & 0xff; | |
539 | tmp[3+len] = (size >> 32) & 0xff; | |
540 | tmp[4+len] = (size >> 24) & 0xff; | |
541 | tmp[5+len] = (size >> 16) & 0xff; | |
542 | tmp[6+len] = (size >> 8) & 0xff; | |
543 | tmp[7+len] = (size ) & 0xff; | |
544 | len += 8; | |
545 | } else { | |
546 | tmp[0+len] = (size >> 24) & 0xff; | |
547 | tmp[1+len] = (size >> 16) & 0xff; | |
548 | tmp[2+len] = (size >> 8) & 0xff; | |
549 | tmp[3+len] = (size ) & 0xff; | |
550 | len += 4; | |
551 | } | |
552 | ||
553 | err = fdt_setprop(blob, nodeoffset, "reg", tmp, len); | |
554 | if (err < 0) { | |
555 | printf("WARNING: could not set %s %s.\n", | |
556 | "reg", fdt_strerror(err)); | |
557 | return err; | |
558 | } | |
559 | return 0; | |
560 | } | |
561 | ||
c01b17dd GVB |
562 | #if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) ||\ |
563 | defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3) | |
564 | ||
ab544633 KG |
565 | void fdt_fixup_ethernet(void *fdt, bd_t *bd) |
566 | { | |
567 | int node; | |
568 | const char *path; | |
569 | ||
570 | node = fdt_path_offset(fdt, "/aliases"); | |
571 | if (node >= 0) { | |
572 | #if defined(CONFIG_HAS_ETH0) | |
573 | path = fdt_getprop(fdt, node, "ethernet0", NULL); | |
574 | if (path) { | |
575 | do_fixup_by_path(fdt, path, "mac-address", | |
576 | bd->bi_enetaddr, 6, 0); | |
577 | do_fixup_by_path(fdt, path, "local-mac-address", | |
578 | bd->bi_enetaddr, 6, 1); | |
579 | } | |
580 | #endif | |
581 | #if defined(CONFIG_HAS_ETH1) | |
582 | path = fdt_getprop(fdt, node, "ethernet1", NULL); | |
583 | if (path) { | |
584 | do_fixup_by_path(fdt, path, "mac-address", | |
585 | bd->bi_enet1addr, 6, 0); | |
586 | do_fixup_by_path(fdt, path, "local-mac-address", | |
587 | bd->bi_enet1addr, 6, 1); | |
588 | } | |
589 | #endif | |
590 | #if defined(CONFIG_HAS_ETH2) | |
591 | path = fdt_getprop(fdt, node, "ethernet2", NULL); | |
592 | if (path) { | |
593 | do_fixup_by_path(fdt, path, "mac-address", | |
594 | bd->bi_enet2addr, 6, 0); | |
595 | do_fixup_by_path(fdt, path, "local-mac-address", | |
596 | bd->bi_enet2addr, 6, 1); | |
597 | } | |
598 | #endif | |
599 | #if defined(CONFIG_HAS_ETH3) | |
600 | path = fdt_getprop(fdt, node, "ethernet3", NULL); | |
601 | if (path) { | |
602 | do_fixup_by_path(fdt, path, "mac-address", | |
603 | bd->bi_enet3addr, 6, 0); | |
604 | do_fixup_by_path(fdt, path, "local-mac-address", | |
605 | bd->bi_enet3addr, 6, 1); | |
606 | } | |
607 | #endif | |
608 | } | |
609 | } | |
c01b17dd | 610 | #endif |