From: Simon Glass Date: Fri, 3 Feb 2012 15:13:53 +0000 (+0000) Subject: fdt: Add function to allow aliases to refer to multiple nodes X-Git-Tag: v2012.04-rc1~19^2~17 X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=commitdiff_plain;h=c67822704b73dcfb86debf4c25151e43309af844 fdt: Add function to allow aliases to refer to multiple nodes Some devices can deal with multiple compatible properties. The devices need to know which nodes to bind to which features. For example an I2C driver which supports two different controller types will want to know which type it is dealing with in each case. The new fdtdec_add_aliases_for_id() function deals with this by allowing the driver to search for additional compatible nodes for a different ID. It can then detect the new ones and perform appropriate processing. Another option considered was to return a tuple (node offset, compat id) and have the function be passed a list of compatible IDs. This is more overhead for the common case though. We may add such a function later if more drivers in U-Boot require it. Signed-off-by: Simon Glass Signed-off-by: Tom Warren --- diff --git a/include/fdtdec.h b/include/fdtdec.h index 6249f22e81..1e198f8c63 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -212,6 +212,29 @@ int fdtdec_check_fdt(void); int fdtdec_find_aliases_for_id(const void *blob, const char *name, enum fdt_compat_id id, int *node_list, int maxcount); +/* + * This function is similar to fdtdec_find_aliases_for_id() except that it + * adds to the node_list that is passed in. Any 0 elements are considered + * available for allocation - others are considered already used and are + * skipped. + * + * You can use this by calling fdtdec_find_aliases_for_id() with an + * uninitialised array, then setting the elements that are returned to -1, + * say, then calling this function, perhaps with a different compat id. + * Any elements you get back that are >0 are new nodes added by the call + * to this function. + * + * Note that if you have some nodes with aliases and some without, you are + * sailing close to the wind. The call to fdtdec_find_aliases_for_id() with + * one compat_id may fill in positions for which you have aliases defined + * for another compat_id. When you later call *this* function with the second + * compat_id, the alias positions may already be used. A debug warning may + * be generated in this case, but it is safest to define aliases for all + * nodes when you care about the ordering. + */ +int fdtdec_add_aliases_for_id(const void *blob, const char *name, + enum fdt_compat_id id, int *node_list, int maxcount); + /* * Get the name for a compatible ID * diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 5239e79479..2149bd7068 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -153,9 +153,17 @@ int fdtdec_next_alias(const void *blob, const char *name, return node; } -/* TODO: Can we tighten this code up a little? */ int fdtdec_find_aliases_for_id(const void *blob, const char *name, enum fdt_compat_id id, int *node_list, int maxcount) +{ + memset(node_list, '\0', sizeof(*node_list) * maxcount); + + return fdtdec_add_aliases_for_id(blob, name, id, node_list, maxcount); +} + +/* TODO: Can we tighten this code up a little? */ +int fdtdec_add_aliases_for_id(const void *blob, const char *name, + enum fdt_compat_id id, int *node_list, int maxcount) { int name_len = strlen(name); int nodes[maxcount]; @@ -185,8 +193,6 @@ int fdtdec_find_aliases_for_id(const void *blob, const char *name, __func__, name); /* Now find all the aliases */ - memset(node_list, '\0', sizeof(*node_list) * maxcount); - for (offset = fdt_first_property_offset(blob, alias_node); offset > 0; offset = fdt_next_property_offset(blob, offset)) { @@ -233,11 +239,19 @@ int fdtdec_find_aliases_for_id(const void *blob, const char *name, * it as done. */ if (fdtdec_get_is_enabled(blob, node)) { + if (node_list[number]) { + debug("%s: warning: alias '%s' requires that " + "a node be placed in the list in a " + "position which is already filled by " + "node '%s'\n", __func__, path, + fdt_get_name(blob, node, NULL)); + continue; + } node_list[number] = node; if (number >= num_found) num_found = number + 1; } - nodes[j] = 0; + nodes[found] = 0; } /* Add any nodes not mentioned by an alias */