diff options
Diffstat (limited to 'common/fdt_support.c')
| -rw-r--r-- | common/fdt_support.c | 183 | 
1 files changed, 161 insertions, 22 deletions
diff --git a/common/fdt_support.c b/common/fdt_support.c index 175d59eb9..c67bb3d39 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -44,6 +44,32 @@ struct fdt_header *fdt;  /********************************************************************/ +/** + * fdt_find_and_setprop: Find a node and set it's property + * + * @fdt: ptr to device tree + * @node: path of node + * @prop: property name + * @val: ptr to new value + * @len: length of new property value + * @create: flag to create the property if it doesn't exist + * + * Convenience function to directly set a property given the path to the node. + */ +int fdt_find_and_setprop(void *fdt, const char *node, const char *prop, +			 const void *val, int len, int create) +{ +	int nodeoff = fdt_path_offset(fdt, node); + +	if (nodeoff < 0) +		return nodeoff; + +	if ((!create) && (fdt_get_property(fdt, nodeoff, prop, 0) == NULL)) +		return 0; /* create flag not set; so exit quietly */ + +	return fdt_setprop(fdt, nodeoff, prop, val, len); +} +  int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)  {  	int   nodeoffset; @@ -58,34 +84,23 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)  	}  	if (initrd_start && initrd_end) { -		struct fdt_reserve_entry re; -		int  used; -		int  total; +		uint64_t addr, size; +		int  total = fdt_num_mem_rsv(fdt);  		int  j; -		err = fdt_num_reservemap(fdt, &used, &total); -		if (err < 0) { -			printf("fdt_chosen: %s\n", fdt_strerror(err)); -			return err; -		} -		if (used >= total) { -			printf("WARNING: " -				"no room in the reserved map (%d of %d)\n", -				used, total); -			return -1; -		}  		/*  		 * Look for an existing entry and update it.  If we don't find  		 * the entry, we will j be the next available slot.  		 */ -		for (j = 0; j < used; j++) { -			err = fdt_get_reservemap(fdt, j, &re); -			if (re.address == initrd_start) { +		for (j = 0; j < total; j++) { +			err = fdt_get_mem_rsv(fdt, j, &addr, &size); +			if (addr == initrd_start) { +				fdt_del_mem_rsv(fdt, j);  				break;  			}  		} -		err = fdt_replace_reservemap_entry(fdt, j, -			initrd_start, initrd_end - initrd_start + 1); + +		err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start + 1);  		if (err < 0) {  			printf("fdt_chosen: %s\n", fdt_strerror(err));  			return err; @@ -95,7 +110,7 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)  	/*  	 * Find the "chosen" node.  	 */ -	nodeoffset = fdt_find_node_by_path (fdt, "/chosen"); +	nodeoffset = fdt_path_offset (fdt, "/chosen");  	/*  	 * If we have a "chosen" node already the "force the writing" @@ -182,7 +197,7 @@ int fdt_env(void *fdt)  	 * See if we already have a "u-boot-env" node, delete it if so.  	 * Then create a new empty node.  	 */ -	nodeoffset = fdt_find_node_by_path (fdt, "/u-boot-env"); +	nodeoffset = fdt_path_offset (fdt, "/u-boot-env");  	if (nodeoffset >= 0) {  		err = fdt_del_node(fdt, nodeoffset);  		if (err < 0) { @@ -304,7 +319,7 @@ int fdt_bd_t(void *fdt)  	 * See if we already have a "bd_t" node, delete it if so.  	 * Then create a new empty node.  	 */ -	nodeoffset = fdt_find_node_by_path (fdt, "/bd_t"); +	nodeoffset = fdt_path_offset (fdt, "/bd_t");  	if (nodeoffset >= 0) {  		err = fdt_del_node(fdt, nodeoffset);  		if (err < 0) { @@ -348,4 +363,128 @@ int fdt_bd_t(void *fdt)  }  #endif /* ifdef CONFIG_OF_HAS_BD_T */ +void do_fixup_by_path(void *fdt, const char *path, const char *prop, +		      const void *val, int len, int create) +{ +#if defined(DEBUG) +	int i; +	debug("Updating property '%s/%s' = ", node, prop); +	for (i = 0; i < len; i++) +		debug(" %.2x", *(u8*)(val+i)); +	debug("\n"); +#endif +	int rc = fdt_find_and_setprop(fdt, path, prop, val, len, create); +	if (rc) +		printf("Unable to update property %s:%s, err=%s\n", +			path, prop, fdt_strerror(rc)); +} + +void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop, +			  u32 val, int create) +{ +	val = cpu_to_fdt32(val); +	do_fixup_by_path(fdt, path, prop, &val, sizeof(val), create); +} + +void do_fixup_by_prop(void *fdt, +		      const char *pname, const void *pval, int plen, +		      const char *prop, const void *val, int len, +		      int create) +{ +	int off; +#if defined(DEBUG) +	int i; +	debug("Updating property '%s/%s' = ", node, prop); +	for (i = 0; i < len; i++) +		debug(" %.2x", *(u8*)(val+i)); +	debug("\n"); +#endif +	off = fdt_node_offset_by_prop_value(fdt, -1, pname, pval, plen); +	while (off != -FDT_ERR_NOTFOUND) { +		if (create || (fdt_get_property(fdt, off, prop, 0) != NULL)) +			fdt_setprop(fdt, off, prop, val, len); +		off = fdt_node_offset_by_prop_value(fdt, off, pname, pval, plen); +	} +} + +void do_fixup_by_prop_u32(void *fdt, +			  const char *pname, const void *pval, int plen, +			  const char *prop, u32 val, int create) +{ +	val = cpu_to_fdt32(val); +	do_fixup_by_prop(fdt, pname, pval, plen, prop, &val, 4, create); +} + +void do_fixup_by_compat(void *fdt, const char *compat, +			const char *prop, const void *val, int len, int create) +{ +	int off = -1; +#if defined(DEBUG) +	int i; +	debug("Updating property '%s/%s' = ", node, prop); +	for (i = 0; i < len; i++) +		debug(" %.2x", *(u8*)(val+i)); +	debug("\n"); +#endif +	off = fdt_node_offset_by_compatible(fdt, -1, compat); +	while (off != -FDT_ERR_NOTFOUND) { +		if (create || (fdt_get_property(fdt, off, prop, 0) != NULL)) +			fdt_setprop(fdt, off, prop, val, len); +		off = fdt_node_offset_by_compatible(fdt, off, compat); +	} +} + +void do_fixup_by_compat_u32(void *fdt, const char *compat, +			    const char *prop, u32 val, int create) +{ +	val = cpu_to_fdt32(val); +	do_fixup_by_compat(fdt, compat, prop, &val, 4, create); +} + +void fdt_fixup_ethernet(void *fdt, bd_t *bd) +{ +	int node; +	const char *path; + +	node = fdt_path_offset(fdt, "/aliases"); +	if (node >= 0) { +#if defined(CONFIG_HAS_ETH0) +		path = fdt_getprop(fdt, node, "ethernet0", NULL); +		if (path) { +			do_fixup_by_path(fdt, path, "mac-address", +				bd->bi_enetaddr, 6, 0); +			do_fixup_by_path(fdt, path, "local-mac-address", +				bd->bi_enetaddr, 6, 1); +		} +#endif +#if defined(CONFIG_HAS_ETH1) +		path = fdt_getprop(fdt, node, "ethernet1", NULL); +		if (path) { +			do_fixup_by_path(fdt, path, "mac-address", +				bd->bi_enet1addr, 6, 0); +			do_fixup_by_path(fdt, path, "local-mac-address", +				bd->bi_enet1addr, 6, 1); +		} +#endif +#if defined(CONFIG_HAS_ETH2) +		path = fdt_getprop(fdt, node, "ethernet2", NULL); +		if (path) { +			do_fixup_by_path(fdt, path, "mac-address", +				bd->bi_enet2addr, 6, 0); +			do_fixup_by_path(fdt, path, "local-mac-address", +				bd->bi_enet2addr, 6, 1); +		} +#endif +#if defined(CONFIG_HAS_ETH3) +		path = fdt_getprop(fdt, node, "ethernet3", NULL); +		if (path) { +			do_fixup_by_path(fdt, path, "mac-address", +				bd->bi_enet3addr, 6, 0); +			do_fixup_by_path(fdt, path, "local-mac-address", +				bd->bi_enet3addr, 6, 1); +		} +#endif +	} +} +  #endif /* CONFIG_OF_LIBFDT */  |