xref: /openbmc/u-boot/common/fdt_support.c (revision ab544633)
164dbbd40SGerald Van Baren /*
264dbbd40SGerald Van Baren  * (C) Copyright 2007
364dbbd40SGerald Van Baren  * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
464dbbd40SGerald Van Baren  *
564dbbd40SGerald Van Baren  * See file CREDITS for list of people who contributed to this
664dbbd40SGerald Van Baren  * project.
764dbbd40SGerald Van Baren  *
864dbbd40SGerald Van Baren  * This program is free software; you can redistribute it and/or
964dbbd40SGerald Van Baren  * modify it under the terms of the GNU General Public License as
1064dbbd40SGerald Van Baren  * published by the Free Software Foundation; either version 2 of
1164dbbd40SGerald Van Baren  * the License, or (at your option) any later version.
1264dbbd40SGerald Van Baren  *
1364dbbd40SGerald Van Baren  * This program is distributed in the hope that it will be useful,
1464dbbd40SGerald Van Baren  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1564dbbd40SGerald Van Baren  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1664dbbd40SGerald Van Baren  * GNU General Public License for more details.
1764dbbd40SGerald Van Baren  *
1864dbbd40SGerald Van Baren  * You should have received a copy of the GNU General Public License
1964dbbd40SGerald Van Baren  * along with this program; if not, write to the Free Software
2064dbbd40SGerald Van Baren  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
2164dbbd40SGerald Van Baren  * MA 02111-1307 USA
2264dbbd40SGerald Van Baren  */
2364dbbd40SGerald Van Baren 
2464dbbd40SGerald Van Baren #include <common.h>
2564dbbd40SGerald Van Baren #include <linux/ctype.h>
2664dbbd40SGerald Van Baren #include <linux/types.h>
2764dbbd40SGerald Van Baren 
2864dbbd40SGerald Van Baren #ifdef CONFIG_OF_LIBFDT
2964dbbd40SGerald Van Baren 
3064dbbd40SGerald Van Baren #include <asm/global_data.h>
3164dbbd40SGerald Van Baren #include <fdt.h>
3264dbbd40SGerald Van Baren #include <libfdt.h>
3364dbbd40SGerald Van Baren #include <fdt_support.h>
3464dbbd40SGerald Van Baren 
3564dbbd40SGerald Van Baren /*
3664dbbd40SGerald Van Baren  * Global data (for the gd->bd)
3764dbbd40SGerald Van Baren  */
3864dbbd40SGerald Van Baren DECLARE_GLOBAL_DATA_PTR;
3964dbbd40SGerald Van Baren 
40bb930e76SGerald Van Baren /*
41bb930e76SGerald Van Baren  * fdt points to our working device tree.
42bb930e76SGerald Van Baren  */
43bb930e76SGerald Van Baren struct fdt_header *fdt;
44bb930e76SGerald Van Baren 
4564dbbd40SGerald Van Baren /********************************************************************/
4664dbbd40SGerald Van Baren 
47a3c2933eSKumar Gala /**
48a3c2933eSKumar Gala  * fdt_find_and_setprop: Find a node and set it's property
49a3c2933eSKumar Gala  *
50a3c2933eSKumar Gala  * @fdt: ptr to device tree
51a3c2933eSKumar Gala  * @node: path of node
52a3c2933eSKumar Gala  * @prop: property name
53a3c2933eSKumar Gala  * @val: ptr to new value
54a3c2933eSKumar Gala  * @len: length of new property value
55a3c2933eSKumar Gala  * @create: flag to create the property if it doesn't exist
56a3c2933eSKumar Gala  *
57a3c2933eSKumar Gala  * Convenience function to directly set a property given the path to the node.
58a3c2933eSKumar Gala  */
59a3c2933eSKumar Gala int fdt_find_and_setprop(void *fdt, const char *node, const char *prop,
60a3c2933eSKumar Gala 			 const void *val, int len, int create)
61a3c2933eSKumar Gala {
628d04f02fSKumar Gala 	int nodeoff = fdt_path_offset(fdt, node);
63a3c2933eSKumar Gala 
64a3c2933eSKumar Gala 	if (nodeoff < 0)
65a3c2933eSKumar Gala 		return nodeoff;
66a3c2933eSKumar Gala 
67a3c2933eSKumar Gala 	if ((!create) && (fdt_get_property(fdt, nodeoff, prop, 0) == NULL))
68a3c2933eSKumar Gala 		return 0; /* create flag not set; so exit quietly */
69a3c2933eSKumar Gala 
70a3c2933eSKumar Gala 	return fdt_setprop(fdt, nodeoff, prop, val, len);
71a3c2933eSKumar Gala }
72a3c2933eSKumar Gala 
7364dbbd40SGerald Van Baren int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)
7464dbbd40SGerald Van Baren {
7564dbbd40SGerald Van Baren 	int   nodeoffset;
7664dbbd40SGerald Van Baren 	int   err;
7764dbbd40SGerald Van Baren 	u32   tmp;		/* used to set 32 bit integer properties */
7864dbbd40SGerald Van Baren 	char  *str;		/* used to set string properties */
7964dbbd40SGerald Van Baren 
8064dbbd40SGerald Van Baren 	err = fdt_check_header(fdt);
8164dbbd40SGerald Van Baren 	if (err < 0) {
825fe6be62SGerald Van Baren 		printf("fdt_chosen: %s\n", fdt_strerror(err));
8364dbbd40SGerald Van Baren 		return err;
8464dbbd40SGerald Van Baren 	}
8564dbbd40SGerald Van Baren 
8664dbbd40SGerald Van Baren 	if (initrd_start && initrd_end) {
878d04f02fSKumar Gala 		uint64_t addr, size;
888d04f02fSKumar Gala 		int  total = fdt_num_mem_rsv(fdt);
89c28abb9cSGerald Van Baren 		int  j;
90c28abb9cSGerald Van Baren 
91c28abb9cSGerald Van Baren 		/*
92c28abb9cSGerald Van Baren 		 * Look for an existing entry and update it.  If we don't find
93c28abb9cSGerald Van Baren 		 * the entry, we will j be the next available slot.
94c28abb9cSGerald Van Baren 		 */
958d04f02fSKumar Gala 		for (j = 0; j < total; j++) {
968d04f02fSKumar Gala 			err = fdt_get_mem_rsv(fdt, j, &addr, &size);
978d04f02fSKumar Gala 			if (addr == initrd_start) {
988d04f02fSKumar Gala 				fdt_del_mem_rsv(fdt, j);
99c28abb9cSGerald Van Baren 				break;
100c28abb9cSGerald Van Baren 			}
101c28abb9cSGerald Van Baren 		}
1028d04f02fSKumar Gala 
1038d04f02fSKumar Gala 		err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start + 1);
10464dbbd40SGerald Van Baren 		if (err < 0) {
1055fe6be62SGerald Van Baren 			printf("fdt_chosen: %s\n", fdt_strerror(err));
10664dbbd40SGerald Van Baren 			return err;
10764dbbd40SGerald Van Baren 		}
10864dbbd40SGerald Van Baren 	}
10964dbbd40SGerald Van Baren 
11064dbbd40SGerald Van Baren 	/*
11164dbbd40SGerald Van Baren 	 * Find the "chosen" node.
11264dbbd40SGerald Van Baren 	 */
1138d04f02fSKumar Gala 	nodeoffset = fdt_path_offset (fdt, "/chosen");
11464dbbd40SGerald Van Baren 
11564dbbd40SGerald Van Baren 	/*
11664dbbd40SGerald Van Baren 	 * If we have a "chosen" node already the "force the writing"
11764dbbd40SGerald Van Baren 	 * is not set, our job is done.
11864dbbd40SGerald Van Baren 	 */
11964dbbd40SGerald Van Baren 	if ((nodeoffset >= 0) && !force)
12064dbbd40SGerald Van Baren 		return 0;
12164dbbd40SGerald Van Baren 
12264dbbd40SGerald Van Baren 	/*
12364dbbd40SGerald Van Baren 	 * No "chosen" node in the blob: create it.
12464dbbd40SGerald Van Baren 	 */
12564dbbd40SGerald Van Baren 	if (nodeoffset < 0) {
12664dbbd40SGerald Van Baren 		/*
12764dbbd40SGerald Van Baren 		 * Create a new node "/chosen" (offset 0 is root level)
12864dbbd40SGerald Van Baren 		 */
12964dbbd40SGerald Van Baren 		nodeoffset = fdt_add_subnode(fdt, 0, "chosen");
13064dbbd40SGerald Van Baren 		if (nodeoffset < 0) {
1315fe6be62SGerald Van Baren 			printf("WARNING: could not create /chosen %s.\n",
13235ec398fSGerald Van Baren 				fdt_strerror(nodeoffset));
13364dbbd40SGerald Van Baren 			return nodeoffset;
13464dbbd40SGerald Van Baren 		}
13564dbbd40SGerald Van Baren 	}
13664dbbd40SGerald Van Baren 
13764dbbd40SGerald Van Baren 	/*
13864dbbd40SGerald Van Baren 	 * Update pre-existing properties, create them if non-existant.
13964dbbd40SGerald Van Baren 	 */
14064dbbd40SGerald Van Baren 	str = getenv("bootargs");
14164dbbd40SGerald Van Baren 	if (str != NULL) {
14235ec398fSGerald Van Baren 		err = fdt_setprop(fdt, nodeoffset,
14335ec398fSGerald Van Baren 			"bootargs", str, strlen(str)+1);
14464dbbd40SGerald Van Baren 		if (err < 0)
1455fe6be62SGerald Van Baren 			printf("WARNING: could not set bootargs %s.\n",
14635ec398fSGerald Van Baren 				fdt_strerror(err));
14764dbbd40SGerald Van Baren 	}
14864dbbd40SGerald Van Baren 	if (initrd_start && initrd_end) {
14964dbbd40SGerald Van Baren 		tmp = __cpu_to_be32(initrd_start);
15035ec398fSGerald Van Baren 		err = fdt_setprop(fdt, nodeoffset,
15135ec398fSGerald Van Baren 			 "linux,initrd-start", &tmp, sizeof(tmp));
15264dbbd40SGerald Van Baren 		if (err < 0)
1535fe6be62SGerald Van Baren 			printf("WARNING: "
1545fe6be62SGerald Van Baren 				"could not set linux,initrd-start %s.\n",
15535ec398fSGerald Van Baren 				fdt_strerror(err));
15664dbbd40SGerald Van Baren 		tmp = __cpu_to_be32(initrd_end);
15735ec398fSGerald Van Baren 		err = fdt_setprop(fdt, nodeoffset,
15835ec398fSGerald Van Baren 			"linux,initrd-end", &tmp, sizeof(tmp));
15964dbbd40SGerald Van Baren 		if (err < 0)
1605fe6be62SGerald Van Baren 			printf("WARNING: could not set linux,initrd-end %s.\n",
16135ec398fSGerald Van Baren 				fdt_strerror(err));
16264dbbd40SGerald Van Baren 	}
16364dbbd40SGerald Van Baren #ifdef OF_STDOUT_PATH
16435ec398fSGerald Van Baren 	err = fdt_setprop(fdt, nodeoffset,
16535ec398fSGerald Van Baren 		"linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1);
16664dbbd40SGerald Van Baren 	if (err < 0)
1675fe6be62SGerald Van Baren 		printf("WARNING: could not set linux,stdout-path %s.\n",
16835ec398fSGerald Van Baren 			fdt_strerror(err));
16964dbbd40SGerald Van Baren #endif
17064dbbd40SGerald Van Baren 
17164dbbd40SGerald Van Baren 	return err;
17264dbbd40SGerald Van Baren }
17364dbbd40SGerald Van Baren 
17464dbbd40SGerald Van Baren /********************************************************************/
17564dbbd40SGerald Van Baren 
17664dbbd40SGerald Van Baren #ifdef CONFIG_OF_HAS_UBOOT_ENV
17764dbbd40SGerald Van Baren 
17864dbbd40SGerald Van Baren /* Function that returns a character from the environment */
17964dbbd40SGerald Van Baren extern uchar(*env_get_char) (int);
18064dbbd40SGerald Van Baren 
18164dbbd40SGerald Van Baren 
18264dbbd40SGerald Van Baren int fdt_env(void *fdt)
18364dbbd40SGerald Van Baren {
18464dbbd40SGerald Van Baren 	int   nodeoffset;
18564dbbd40SGerald Van Baren 	int   err;
18664dbbd40SGerald Van Baren 	int   k, nxt;
18764dbbd40SGerald Van Baren 	int i;
18864dbbd40SGerald Van Baren 	static char tmpenv[256];
18964dbbd40SGerald Van Baren 
19064dbbd40SGerald Van Baren 	err = fdt_check_header(fdt);
19164dbbd40SGerald Van Baren 	if (err < 0) {
1925fe6be62SGerald Van Baren 		printf("fdt_env: %s\n", fdt_strerror(err));
19364dbbd40SGerald Van Baren 		return err;
19464dbbd40SGerald Van Baren 	}
19564dbbd40SGerald Van Baren 
19664dbbd40SGerald Van Baren 	/*
19764dbbd40SGerald Van Baren 	 * See if we already have a "u-boot-env" node, delete it if so.
19864dbbd40SGerald Van Baren 	 * Then create a new empty node.
19964dbbd40SGerald Van Baren 	 */
2008d04f02fSKumar Gala 	nodeoffset = fdt_path_offset (fdt, "/u-boot-env");
20164dbbd40SGerald Van Baren 	if (nodeoffset >= 0) {
20264dbbd40SGerald Van Baren 		err = fdt_del_node(fdt, nodeoffset);
20364dbbd40SGerald Van Baren 		if (err < 0) {
2045fe6be62SGerald Van Baren 			printf("fdt_env: %s\n", fdt_strerror(err));
20564dbbd40SGerald Van Baren 			return err;
20664dbbd40SGerald Van Baren 		}
20764dbbd40SGerald Van Baren 	}
20864dbbd40SGerald Van Baren 	/*
20964dbbd40SGerald Van Baren 	 * Create a new node "/u-boot-env" (offset 0 is root level)
21064dbbd40SGerald Van Baren 	 */
21164dbbd40SGerald Van Baren 	nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env");
21264dbbd40SGerald Van Baren 	if (nodeoffset < 0) {
2135fe6be62SGerald Van Baren 		printf("WARNING: could not create /u-boot-env %s.\n",
21435ec398fSGerald Van Baren 			fdt_strerror(nodeoffset));
21564dbbd40SGerald Van Baren 		return nodeoffset;
21664dbbd40SGerald Van Baren 	}
21764dbbd40SGerald Van Baren 
21864dbbd40SGerald Van Baren 	for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
21964dbbd40SGerald Van Baren 		char *s, *lval, *rval;
22064dbbd40SGerald Van Baren 
22164dbbd40SGerald Van Baren 		/*
22264dbbd40SGerald Van Baren 		 * Find the end of the name=definition
22364dbbd40SGerald Van Baren 		 */
22464dbbd40SGerald Van Baren 		for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
22564dbbd40SGerald Van Baren 			;
22664dbbd40SGerald Van Baren 		s = tmpenv;
22764dbbd40SGerald Van Baren 		for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k)
22864dbbd40SGerald Van Baren 			*s++ = env_get_char(k);
22964dbbd40SGerald Van Baren 		*s++ = '\0';
23064dbbd40SGerald Van Baren 		lval = tmpenv;
23164dbbd40SGerald Van Baren 		/*
23264dbbd40SGerald Van Baren 		 * Find the first '=': it separates the name from the value
23364dbbd40SGerald Van Baren 		 */
23464dbbd40SGerald Van Baren 		s = strchr(tmpenv, '=');
23564dbbd40SGerald Van Baren 		if (s != NULL) {
23664dbbd40SGerald Van Baren 			*s++ = '\0';
23764dbbd40SGerald Van Baren 			rval = s;
23864dbbd40SGerald Van Baren 		} else
23964dbbd40SGerald Van Baren 			continue;
24064dbbd40SGerald Van Baren 		err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1);
24164dbbd40SGerald Van Baren 		if (err < 0) {
2425fe6be62SGerald Van Baren 			printf("WARNING: could not set %s %s.\n",
24335ec398fSGerald Van Baren 				lval, fdt_strerror(err));
24464dbbd40SGerald Van Baren 			return err;
24564dbbd40SGerald Van Baren 		}
24664dbbd40SGerald Van Baren 	}
24764dbbd40SGerald Van Baren 	return 0;
24864dbbd40SGerald Van Baren }
249c28abb9cSGerald Van Baren #endif /* ifdef CONFIG_OF_HAS_UBOOT_ENV */
25064dbbd40SGerald Van Baren 
25164dbbd40SGerald Van Baren /********************************************************************/
25264dbbd40SGerald Van Baren 
25364dbbd40SGerald Van Baren #ifdef CONFIG_OF_HAS_BD_T
25464dbbd40SGerald Van Baren 
25564dbbd40SGerald Van Baren #define BDM(x)	{	.name = #x, .offset = offsetof(bd_t, bi_ ##x ) }
25664dbbd40SGerald Van Baren 
25764dbbd40SGerald Van Baren static const struct {
25864dbbd40SGerald Van Baren 	const char *name;
25964dbbd40SGerald Van Baren 	int offset;
26064dbbd40SGerald Van Baren } bd_map[] = {
26164dbbd40SGerald Van Baren 	BDM(memstart),
26264dbbd40SGerald Van Baren 	BDM(memsize),
26364dbbd40SGerald Van Baren 	BDM(flashstart),
26464dbbd40SGerald Van Baren 	BDM(flashsize),
26564dbbd40SGerald Van Baren 	BDM(flashoffset),
26664dbbd40SGerald Van Baren 	BDM(sramstart),
26764dbbd40SGerald Van Baren 	BDM(sramsize),
26864dbbd40SGerald Van Baren #if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \
26964dbbd40SGerald Van Baren 	|| defined(CONFIG_E500)
27064dbbd40SGerald Van Baren 	BDM(immr_base),
27164dbbd40SGerald Van Baren #endif
27264dbbd40SGerald Van Baren #if defined(CONFIG_MPC5xxx)
27364dbbd40SGerald Van Baren 	BDM(mbar_base),
27464dbbd40SGerald Van Baren #endif
27564dbbd40SGerald Van Baren #if defined(CONFIG_MPC83XX)
27664dbbd40SGerald Van Baren 	BDM(immrbar),
27764dbbd40SGerald Van Baren #endif
27864dbbd40SGerald Van Baren #if defined(CONFIG_MPC8220)
27964dbbd40SGerald Van Baren 	BDM(mbar_base),
28064dbbd40SGerald Van Baren 	BDM(inpfreq),
28164dbbd40SGerald Van Baren 	BDM(pcifreq),
28264dbbd40SGerald Van Baren 	BDM(pevfreq),
28364dbbd40SGerald Van Baren 	BDM(flbfreq),
28464dbbd40SGerald Van Baren 	BDM(vcofreq),
28564dbbd40SGerald Van Baren #endif
28664dbbd40SGerald Van Baren 	BDM(bootflags),
28764dbbd40SGerald Van Baren 	BDM(ip_addr),
28864dbbd40SGerald Van Baren 	BDM(intfreq),
28964dbbd40SGerald Van Baren 	BDM(busfreq),
29064dbbd40SGerald Van Baren #ifdef CONFIG_CPM2
29164dbbd40SGerald Van Baren 	BDM(cpmfreq),
29264dbbd40SGerald Van Baren 	BDM(brgfreq),
29364dbbd40SGerald Van Baren 	BDM(sccfreq),
29464dbbd40SGerald Van Baren 	BDM(vco),
29564dbbd40SGerald Van Baren #endif
29664dbbd40SGerald Van Baren #if defined(CONFIG_MPC5xxx)
29764dbbd40SGerald Van Baren 	BDM(ipbfreq),
29864dbbd40SGerald Van Baren 	BDM(pcifreq),
29964dbbd40SGerald Van Baren #endif
30064dbbd40SGerald Van Baren 	BDM(baudrate),
30164dbbd40SGerald Van Baren };
30264dbbd40SGerald Van Baren 
30364dbbd40SGerald Van Baren 
30464dbbd40SGerald Van Baren int fdt_bd_t(void *fdt)
30564dbbd40SGerald Van Baren {
30664dbbd40SGerald Van Baren 	bd_t *bd = gd->bd;
30764dbbd40SGerald Van Baren 	int   nodeoffset;
30864dbbd40SGerald Van Baren 	int   err;
30964dbbd40SGerald Van Baren 	u32   tmp;		/* used to set 32 bit integer properties */
31064dbbd40SGerald Van Baren 	int i;
31164dbbd40SGerald Van Baren 
31264dbbd40SGerald Van Baren 	err = fdt_check_header(fdt);
31364dbbd40SGerald Van Baren 	if (err < 0) {
3145fe6be62SGerald Van Baren 		printf("fdt_bd_t: %s\n", fdt_strerror(err));
31564dbbd40SGerald Van Baren 		return err;
31664dbbd40SGerald Van Baren 	}
31764dbbd40SGerald Van Baren 
31864dbbd40SGerald Van Baren 	/*
31964dbbd40SGerald Van Baren 	 * See if we already have a "bd_t" node, delete it if so.
32064dbbd40SGerald Van Baren 	 * Then create a new empty node.
32164dbbd40SGerald Van Baren 	 */
3228d04f02fSKumar Gala 	nodeoffset = fdt_path_offset (fdt, "/bd_t");
32364dbbd40SGerald Van Baren 	if (nodeoffset >= 0) {
32464dbbd40SGerald Van Baren 		err = fdt_del_node(fdt, nodeoffset);
32564dbbd40SGerald Van Baren 		if (err < 0) {
3265fe6be62SGerald Van Baren 			printf("fdt_bd_t: %s\n", fdt_strerror(err));
32764dbbd40SGerald Van Baren 			return err;
32864dbbd40SGerald Van Baren 		}
32964dbbd40SGerald Van Baren 	}
33064dbbd40SGerald Van Baren 	/*
33164dbbd40SGerald Van Baren 	 * Create a new node "/bd_t" (offset 0 is root level)
33264dbbd40SGerald Van Baren 	 */
33364dbbd40SGerald Van Baren 	nodeoffset = fdt_add_subnode(fdt, 0, "bd_t");
33464dbbd40SGerald Van Baren 	if (nodeoffset < 0) {
3355fe6be62SGerald Van Baren 		printf("WARNING: could not create /bd_t %s.\n",
33635ec398fSGerald Van Baren 			fdt_strerror(nodeoffset));
3375fe6be62SGerald Van Baren 		printf("fdt_bd_t: %s\n", fdt_strerror(nodeoffset));
33864dbbd40SGerald Van Baren 		return nodeoffset;
33964dbbd40SGerald Van Baren 	}
34064dbbd40SGerald Van Baren 	/*
34164dbbd40SGerald Van Baren 	 * Use the string/pointer structure to create the entries...
34264dbbd40SGerald Van Baren 	 */
34364dbbd40SGerald Van Baren 	for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) {
34464dbbd40SGerald Van Baren 		tmp = cpu_to_be32(getenv("bootargs"));
34535ec398fSGerald Van Baren 		err = fdt_setprop(fdt, nodeoffset,
34635ec398fSGerald Van Baren 			bd_map[i].name, &tmp, sizeof(tmp));
34764dbbd40SGerald Van Baren 		if (err < 0)
3485fe6be62SGerald Van Baren 			printf("WARNING: could not set %s %s.\n",
34935ec398fSGerald Van Baren 				bd_map[i].name, fdt_strerror(err));
35064dbbd40SGerald Van Baren 	}
35164dbbd40SGerald Van Baren 	/*
35264dbbd40SGerald Van Baren 	 * Add a couple of oddball entries...
35364dbbd40SGerald Van Baren 	 */
35464dbbd40SGerald Van Baren 	err = fdt_setprop(fdt, nodeoffset, "enetaddr", &bd->bi_enetaddr, 6);
35564dbbd40SGerald Van Baren 	if (err < 0)
3565fe6be62SGerald Van Baren 		printf("WARNING: could not set enetaddr %s.\n",
35735ec398fSGerald Van Baren 			fdt_strerror(err));
35864dbbd40SGerald Van Baren 	err = fdt_setprop(fdt, nodeoffset, "ethspeed", &bd->bi_ethspeed, 4);
35964dbbd40SGerald Van Baren 	if (err < 0)
3605fe6be62SGerald Van Baren 		printf("WARNING: could not set ethspeed %s.\n",
36135ec398fSGerald Van Baren 			fdt_strerror(err));
36264dbbd40SGerald Van Baren 	return 0;
36364dbbd40SGerald Van Baren }
364c28abb9cSGerald Van Baren #endif /* ifdef CONFIG_OF_HAS_BD_T */
36564dbbd40SGerald Van Baren 
366e93becf8SKumar Gala void do_fixup_by_path(void *fdt, const char *path, const char *prop,
367e93becf8SKumar Gala 		      const void *val, int len, int create)
368e93becf8SKumar Gala {
369e93becf8SKumar Gala #if defined(DEBUG)
370e93becf8SKumar Gala 	int i;
371e93becf8SKumar Gala 	debug("Updating property '%s/%s' = ", node, prop);
372e93becf8SKumar Gala 	for (i = 0; i < len; i++)
373e93becf8SKumar Gala 		debug(" %.2x", *(u8*)(val+i));
374e93becf8SKumar Gala 	debug("\n");
375e93becf8SKumar Gala #endif
376e93becf8SKumar Gala 	int rc = fdt_find_and_setprop(fdt, path, prop, val, len, create);
377e93becf8SKumar Gala 	if (rc)
378e93becf8SKumar Gala 		printf("Unable to update property %s:%s, err=%s\n",
379e93becf8SKumar Gala 			path, prop, fdt_strerror(rc));
380e93becf8SKumar Gala }
381e93becf8SKumar Gala 
382e93becf8SKumar Gala void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop,
383e93becf8SKumar Gala 			  u32 val, int create)
384e93becf8SKumar Gala {
385e93becf8SKumar Gala 	val = cpu_to_fdt32(val);
386e93becf8SKumar Gala 	do_fixup_by_path(fdt, path, prop, &val, sizeof(val), create);
387e93becf8SKumar Gala }
388e93becf8SKumar Gala 
389*ab544633SKumar Gala void fdt_fixup_ethernet(void *fdt, bd_t *bd)
390*ab544633SKumar Gala {
391*ab544633SKumar Gala 	int node;
392*ab544633SKumar Gala 	const char *path;
393*ab544633SKumar Gala 
394*ab544633SKumar Gala 	node = fdt_path_offset(fdt, "/aliases");
395*ab544633SKumar Gala 	if (node >= 0) {
396*ab544633SKumar Gala #if defined(CONFIG_HAS_ETH0)
397*ab544633SKumar Gala 		path = fdt_getprop(fdt, node, "ethernet0", NULL);
398*ab544633SKumar Gala 		if (path) {
399*ab544633SKumar Gala 			do_fixup_by_path(fdt, path, "mac-address",
400*ab544633SKumar Gala 				bd->bi_enetaddr, 6, 0);
401*ab544633SKumar Gala 			do_fixup_by_path(fdt, path, "local-mac-address",
402*ab544633SKumar Gala 				bd->bi_enetaddr, 6, 1);
403*ab544633SKumar Gala 		}
404*ab544633SKumar Gala #endif
405*ab544633SKumar Gala #if defined(CONFIG_HAS_ETH1)
406*ab544633SKumar Gala 		path = fdt_getprop(fdt, node, "ethernet1", NULL);
407*ab544633SKumar Gala 		if (path) {
408*ab544633SKumar Gala 			do_fixup_by_path(fdt, path, "mac-address",
409*ab544633SKumar Gala 				bd->bi_enet1addr, 6, 0);
410*ab544633SKumar Gala 			do_fixup_by_path(fdt, path, "local-mac-address",
411*ab544633SKumar Gala 				bd->bi_enet1addr, 6, 1);
412*ab544633SKumar Gala 		}
413*ab544633SKumar Gala #endif
414*ab544633SKumar Gala #if defined(CONFIG_HAS_ETH2)
415*ab544633SKumar Gala 		path = fdt_getprop(fdt, node, "ethernet2", NULL);
416*ab544633SKumar Gala 		if (path) {
417*ab544633SKumar Gala 			do_fixup_by_path(fdt, path, "mac-address",
418*ab544633SKumar Gala 				bd->bi_enet2addr, 6, 0);
419*ab544633SKumar Gala 			do_fixup_by_path(fdt, path, "local-mac-address",
420*ab544633SKumar Gala 				bd->bi_enet2addr, 6, 1);
421*ab544633SKumar Gala 		}
422*ab544633SKumar Gala #endif
423*ab544633SKumar Gala #if defined(CONFIG_HAS_ETH3)
424*ab544633SKumar Gala 		path = fdt_getprop(fdt, node, "ethernet3", NULL);
425*ab544633SKumar Gala 		if (path) {
426*ab544633SKumar Gala 			do_fixup_by_path(fdt, path, "mac-address",
427*ab544633SKumar Gala 				bd->bi_enet3addr, 6, 0);
428*ab544633SKumar Gala 			do_fixup_by_path(fdt, path, "local-mac-address",
429*ab544633SKumar Gala 				bd->bi_enet3addr, 6, 1);
430*ab544633SKumar Gala 		}
431*ab544633SKumar Gala #endif
432*ab544633SKumar Gala 	}
433*ab544633SKumar Gala }
434*ab544633SKumar Gala 
43564dbbd40SGerald Van Baren #endif /* CONFIG_OF_LIBFDT */
436