]>
git.ipfire.org Git - people/ms/u-boot.git/blob - common/fdt_support.c
3 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
5 * See file CREDITS for list of people who contributed to this
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.
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.
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,
25 #include <linux/ctype.h>
26 #include <linux/types.h>
28 #ifdef CONFIG_OF_LIBFDT
30 #include <asm/global_data.h>
33 #include <fdt_support.h>
36 * Global data (for the gd->bd)
38 DECLARE_GLOBAL_DATA_PTR
;
41 * fdt points to our working device tree.
43 struct fdt_header
*fdt
;
45 /********************************************************************/
48 * fdt_find_and_setprop: Find a node and set it's property
50 * @fdt: ptr to device tree
52 * @prop: property name
53 * @val: ptr to new value
54 * @len: length of new property value
55 * @create: flag to create the property if it doesn't exist
57 * Convenience function to directly set a property given the path to the node.
59 int fdt_find_and_setprop(void *fdt
, const char *node
, const char *prop
,
60 const void *val
, int len
, int create
)
62 int nodeoff
= fdt_path_offset(fdt
, node
);
67 if ((!create
) && (fdt_get_property(fdt
, nodeoff
, prop
, 0) == NULL
))
68 return 0; /* create flag not set; so exit quietly */
70 return fdt_setprop(fdt
, nodeoff
, prop
, val
, len
);
73 int fdt_chosen(void *fdt
, ulong initrd_start
, ulong initrd_end
, int force
)
77 u32 tmp
; /* used to set 32 bit integer properties */
78 char *str
; /* used to set string properties */
80 err
= fdt_check_header(fdt
);
82 printf("fdt_chosen: %s\n", fdt_strerror(err
));
86 if (initrd_start
&& initrd_end
) {
88 int total
= fdt_num_mem_rsv(fdt
);
92 * Look for an existing entry and update it. If we don't find
93 * the entry, we will j be the next available slot.
95 for (j
= 0; j
< total
; j
++) {
96 err
= fdt_get_mem_rsv(fdt
, j
, &addr
, &size
);
97 if (addr
== initrd_start
) {
98 fdt_del_mem_rsv(fdt
, j
);
103 err
= fdt_add_mem_rsv(fdt
, initrd_start
, initrd_end
- initrd_start
+ 1);
105 printf("fdt_chosen: %s\n", fdt_strerror(err
));
111 * Find the "chosen" node.
113 nodeoffset
= fdt_path_offset (fdt
, "/chosen");
116 * If we have a "chosen" node already the "force the writing"
117 * is not set, our job is done.
119 if ((nodeoffset
>= 0) && !force
)
123 * No "chosen" node in the blob: create it.
125 if (nodeoffset
< 0) {
127 * Create a new node "/chosen" (offset 0 is root level)
129 nodeoffset
= fdt_add_subnode(fdt
, 0, "chosen");
130 if (nodeoffset
< 0) {
131 printf("WARNING: could not create /chosen %s.\n",
132 fdt_strerror(nodeoffset
));
138 * Update pre-existing properties, create them if non-existant.
140 str
= getenv("bootargs");
142 err
= fdt_setprop(fdt
, nodeoffset
,
143 "bootargs", str
, strlen(str
)+1);
145 printf("WARNING: could not set bootargs %s.\n",
148 if (initrd_start
&& initrd_end
) {
149 tmp
= __cpu_to_be32(initrd_start
);
150 err
= fdt_setprop(fdt
, nodeoffset
,
151 "linux,initrd-start", &tmp
, sizeof(tmp
));
154 "could not set linux,initrd-start %s.\n",
156 tmp
= __cpu_to_be32(initrd_end
);
157 err
= fdt_setprop(fdt
, nodeoffset
,
158 "linux,initrd-end", &tmp
, sizeof(tmp
));
160 printf("WARNING: could not set linux,initrd-end %s.\n",
163 #ifdef OF_STDOUT_PATH
164 err
= fdt_setprop(fdt
, nodeoffset
,
165 "linux,stdout-path", OF_STDOUT_PATH
, strlen(OF_STDOUT_PATH
)+1);
167 printf("WARNING: could not set linux,stdout-path %s.\n",
174 /********************************************************************/
176 #ifdef CONFIG_OF_HAS_UBOOT_ENV
178 /* Function that returns a character from the environment */
179 extern uchar(*env_get_char
) (int);
182 int fdt_env(void *fdt
)
188 static char tmpenv
[256];
190 err
= fdt_check_header(fdt
);
192 printf("fdt_env: %s\n", fdt_strerror(err
));
197 * See if we already have a "u-boot-env" node, delete it if so.
198 * Then create a new empty node.
200 nodeoffset
= fdt_path_offset (fdt
, "/u-boot-env");
201 if (nodeoffset
>= 0) {
202 err
= fdt_del_node(fdt
, nodeoffset
);
204 printf("fdt_env: %s\n", fdt_strerror(err
));
209 * Create a new node "/u-boot-env" (offset 0 is root level)
211 nodeoffset
= fdt_add_subnode(fdt
, 0, "u-boot-env");
212 if (nodeoffset
< 0) {
213 printf("WARNING: could not create /u-boot-env %s.\n",
214 fdt_strerror(nodeoffset
));
218 for (i
= 0; env_get_char(i
) != '\0'; i
= nxt
+ 1) {
219 char *s
, *lval
, *rval
;
222 * Find the end of the name=definition
224 for (nxt
= i
; env_get_char(nxt
) != '\0'; ++nxt
)
227 for (k
= i
; k
< nxt
&& s
< &tmpenv
[sizeof(tmpenv
) - 1]; ++k
)
228 *s
++ = env_get_char(k
);
232 * Find the first '=': it separates the name from the value
234 s
= strchr(tmpenv
, '=');
240 err
= fdt_setprop(fdt
, nodeoffset
, lval
, rval
, strlen(rval
)+1);
242 printf("WARNING: could not set %s %s.\n",
243 lval
, fdt_strerror(err
));
249 #endif /* ifdef CONFIG_OF_HAS_UBOOT_ENV */
251 /********************************************************************/
253 #ifdef CONFIG_OF_HAS_BD_T
255 #define BDM(x) { .name = #x, .offset = offsetof(bd_t, bi_ ##x ) }
257 static const struct {
268 #if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \
269 || defined(CONFIG_E500)
272 #if defined(CONFIG_MPC5xxx)
275 #if defined(CONFIG_MPC83XX)
278 #if defined(CONFIG_MPC8220)
296 #if defined(CONFIG_MPC5xxx)
304 int fdt_bd_t(void *fdt
)
309 u32 tmp
; /* used to set 32 bit integer properties */
312 err
= fdt_check_header(fdt
);
314 printf("fdt_bd_t: %s\n", fdt_strerror(err
));
319 * See if we already have a "bd_t" node, delete it if so.
320 * Then create a new empty node.
322 nodeoffset
= fdt_path_offset (fdt
, "/bd_t");
323 if (nodeoffset
>= 0) {
324 err
= fdt_del_node(fdt
, nodeoffset
);
326 printf("fdt_bd_t: %s\n", fdt_strerror(err
));
331 * Create a new node "/bd_t" (offset 0 is root level)
333 nodeoffset
= fdt_add_subnode(fdt
, 0, "bd_t");
334 if (nodeoffset
< 0) {
335 printf("WARNING: could not create /bd_t %s.\n",
336 fdt_strerror(nodeoffset
));
337 printf("fdt_bd_t: %s\n", fdt_strerror(nodeoffset
));
341 * Use the string/pointer structure to create the entries...
343 for (i
= 0; i
< sizeof(bd_map
)/sizeof(bd_map
[0]); i
++) {
344 tmp
= cpu_to_be32(getenv("bootargs"));
345 err
= fdt_setprop(fdt
, nodeoffset
,
346 bd_map
[i
].name
, &tmp
, sizeof(tmp
));
348 printf("WARNING: could not set %s %s.\n",
349 bd_map
[i
].name
, fdt_strerror(err
));
352 * Add a couple of oddball entries...
354 err
= fdt_setprop(fdt
, nodeoffset
, "enetaddr", &bd
->bi_enetaddr
, 6);
356 printf("WARNING: could not set enetaddr %s.\n",
358 err
= fdt_setprop(fdt
, nodeoffset
, "ethspeed", &bd
->bi_ethspeed
, 4);
360 printf("WARNING: could not set ethspeed %s.\n",
364 #endif /* ifdef CONFIG_OF_HAS_BD_T */
366 void do_fixup_by_path(void *fdt
, const char *path
, const char *prop
,
367 const void *val
, int len
, int create
)
371 debug("Updating property '%s/%s' = ", node
, prop
);
372 for (i
= 0; i
< len
; i
++)
373 debug(" %.2x", *(u8
*)(val
+i
));
376 int rc
= fdt_find_and_setprop(fdt
, path
, prop
, val
, len
, create
);
378 printf("Unable to update property %s:%s, err=%s\n",
379 path
, prop
, fdt_strerror(rc
));
382 void do_fixup_by_path_u32(void *fdt
, const char *path
, const char *prop
,
385 val
= cpu_to_fdt32(val
);
386 do_fixup_by_path(fdt
, path
, prop
, &val
, sizeof(val
), create
);
389 void fdt_fixup_ethernet(void *fdt
, bd_t
*bd
)
394 node
= fdt_path_offset(fdt
, "/aliases");
396 #if defined(CONFIG_HAS_ETH0)
397 path
= fdt_getprop(fdt
, node
, "ethernet0", NULL
);
399 do_fixup_by_path(fdt
, path
, "mac-address",
400 bd
->bi_enetaddr
, 6, 0);
401 do_fixup_by_path(fdt
, path
, "local-mac-address",
402 bd
->bi_enetaddr
, 6, 1);
405 #if defined(CONFIG_HAS_ETH1)
406 path
= fdt_getprop(fdt
, node
, "ethernet1", NULL
);
408 do_fixup_by_path(fdt
, path
, "mac-address",
409 bd
->bi_enet1addr
, 6, 0);
410 do_fixup_by_path(fdt
, path
, "local-mac-address",
411 bd
->bi_enet1addr
, 6, 1);
414 #if defined(CONFIG_HAS_ETH2)
415 path
= fdt_getprop(fdt
, node
, "ethernet2", NULL
);
417 do_fixup_by_path(fdt
, path
, "mac-address",
418 bd
->bi_enet2addr
, 6, 0);
419 do_fixup_by_path(fdt
, path
, "local-mac-address",
420 bd
->bi_enet2addr
, 6, 1);
423 #if defined(CONFIG_HAS_ETH3)
424 path
= fdt_getprop(fdt
, node
, "ethernet3", NULL
);
426 do_fixup_by_path(fdt
, path
, "mac-address",
427 bd
->bi_enet3addr
, 6, 0);
428 do_fixup_by_path(fdt
, path
, "local-mac-address",
429 bd
->bi_enet3addr
, 6, 1);
435 #endif /* CONFIG_OF_LIBFDT */