diff --git a/arch/arm/boards/at91sam9x5ek/hw_version.c b/arch/arm/boards/at91sam9x5ek/hw_version.c index 91af331..1207a3e 100644 --- a/arch/arm/boards/at91sam9x5ek/hw_version.c +++ b/arch/arm/boards/at91sam9x5ek/hw_version.c @@ -234,13 +234,9 @@ int ret; struct device_node *node; - of_tree_for_each_node(node, root) { - struct device_node *slotnode; - - if (!of_device_is_compatible(node, "atmel,hsmci")) - continue; - - slotnode = of_find_child_by_name(node, "slot"); + for_each_compatible_node(node, NULL, "atmel,hsmci") { + struct device_node *slotnode = + of_get_child_by_name(node, "slot"); if (!slotnode) continue; diff --git a/arch/arm/boards/highbank/init.c b/arch/arm/boards/highbank/init.c index d4a5c5a..46ecc88 100644 --- a/arch/arm/boards/highbank/init.c +++ b/arch/arm/boards/highbank/init.c @@ -35,25 +35,21 @@ __be32 latency; if (!(reg & HB_PWRDOM_STAT_SATA)) { - of_tree_for_each_node(node, root) { - if (of_device_is_compatible(node, "calxeda,hb-ahci")) - of_set_property(node, "status", "disabled", - sizeof("disabled"), 1); - } + for_each_compatible_node(node, NULL, "calxeda,hb-ahci") + of_set_property(node, "status", "disabled", + sizeof("disabled"), 1); } if (!(reg & HB_PWRDOM_STAT_EMMC)) { - of_tree_for_each_node(node, root) { - if (of_device_is_compatible(node, "calxeda,hb-sdhci")) - of_set_property(node, "status", "disabled", - sizeof("disabled"), 1); - } + for_each_compatible_node(node, NULL, "calxeda,hb-sdhci") + of_set_property(node, "status", "disabled", + sizeof("disabled"), 1); } if ((opp_table[0] >> 16) != HB_OPP_VERSION) return 0; - node = of_find_node_by_path(root, "/cpus/cpu@0"); + node = of_find_node_by_path("/cpus/cpu@0"); if (!node) return 0; @@ -89,7 +85,7 @@ of_set_root_node(root); - np = of_find_node_by_path(root, "/memory"); + np = of_find_node_by_path("/memory"); if (!np) { pr_warn("no memory node use default configuration\n"); goto not_found; diff --git a/arch/ppc/include/asm/string.h b/arch/ppc/include/asm/string.h index d912a6b..33d143f 100644 --- a/arch/ppc/include/asm/string.h +++ b/arch/ppc/include/asm/string.h @@ -13,8 +13,6 @@ #define __HAVE_ARCH_MEMCMP #define __HAVE_ARCH_MEMCHR -extern int strcasecmp(const char *, const char *); -extern int strncasecmp(const char *, const char *, int); extern char * strcpy(char *,const char *); extern char * strncpy(char *,const char *, __kernel_size_t); extern __kernel_size_t strlen(const char *); diff --git a/arch/ppc/mach-mpc5xxx/cpu.c b/arch/ppc/mach-mpc5xxx/cpu.c index 99f16eb..0ece4a9 100644 --- a/arch/ppc/mach-mpc5xxx/cpu.c +++ b/arch/ppc/mach-mpc5xxx/cpu.c @@ -83,7 +83,7 @@ int div = in_8((void*)CFG_MBAR + 0x204) & 0x0020 ? 8 : 4; - node = of_find_node_by_path(root, "/cpus/PowerPC,5200@0"); + node = of_find_node_by_path("/cpus/PowerPC,5200@0"); if (!node) return -EINVAL; @@ -91,7 +91,7 @@ of_property_write_u32(node, "bus-frequency", get_bus_clock()); of_property_write_u32(node, "clock-frequency", get_cpu_clock()); - node = of_find_node_by_path(root, "/soc5200@f0000000"); + node = of_find_node_by_path("/soc5200@f0000000"); if (!node) return -EINVAL; diff --git a/commands/of_node.c b/commands/of_node.c index 0249d97..e60ef66 100644 --- a/commands/of_node.c +++ b/commands/of_node.c @@ -81,7 +81,7 @@ if (!path) return COMMAND_ERROR_USAGE; - node = of_find_node_by_path(root, path); + node = of_find_node_by_path(path); if (!node) { printf("Cannot find nodepath %s\n", path); return -ENOENT; diff --git a/commands/of_property.c b/commands/of_property.c index 44bb388..8ffe30b 100644 --- a/commands/of_property.c +++ b/commands/of_property.c @@ -175,7 +175,7 @@ int set = 0; int ret; char *path = NULL, *propname = NULL; - struct device_node *root, *node = NULL; + struct device_node *node = NULL; struct property *pp = NULL; while ((opt = getopt(argc, argv, "ds")) > 0) { @@ -194,15 +194,9 @@ if (optind == argc) return COMMAND_ERROR_USAGE; - root = of_get_root_node(); - if (!root) { - printf("root node not set\n"); - return -ENOENT; - } - if (optind < argc) { path = argv[optind]; - node = of_find_node_by_path(root, path); + node = of_find_node_by_path(path); if (!node) { printf("Cannot find nodepath %s\n", path); return -ENOENT; @@ -212,7 +206,7 @@ if (optind + 1 < argc) { propname = argv[optind + 1]; - pp = of_find_property(node, propname); + pp = of_find_property(node, propname, NULL); if (!set && !pp) { printf("Cannot find property %s\n", propname); return -ENOENT; diff --git a/commands/oftree.c b/commands/oftree.c index 468235a..9149517 100644 --- a/commands/oftree.c +++ b/commands/oftree.c @@ -164,16 +164,7 @@ of_print_nodes(root, 0); of_free(root); } else { - struct device_node *root, *n; - - root = of_get_root_node(); - if (!root) { - ret = -ENOENT; - goto out; - } - - n = of_find_node_by_path(root, node); - + struct device_node *n = of_find_node_by_path(node); if (!n) { ret = -ENOENT; goto out; diff --git a/common/oftree.c b/common/oftree.c index 475d418..aff4c28 100644 --- a/common/oftree.c +++ b/common/oftree.c @@ -100,7 +100,7 @@ void of_print_cmdline(struct device_node *root) { - struct device_node *node = of_find_node_by_path(root, "/chosen"); + struct device_node *node = of_find_node_by_path("/chosen"); const char *cmdline; if (!node) { diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c index b63d946..3e09547 100644 --- a/drivers/i2c/i2c.c +++ b/drivers/i2c/i2c.c @@ -278,7 +278,7 @@ if (!IS_ENABLED(CONFIG_OFDEVICE) || !adap->dev.device_node) return; - device_node_for_nach_child(adap->dev.device_node, n) { + for_each_child_of_node(adap->dev.device_node, n) { struct i2c_board_info info = {}; struct i2c_client *result; const __be32 *addr; diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index d785430..3a2db92 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -116,7 +116,7 @@ pdata = xzalloc(sizeof(*pdata)); - device_node_for_nach_child(dev->device_node, node) { + for_each_child_of_node(dev->device_node, node) { if (!strcmp(node->name, "stmpe_gpio")) { pdata->blocks |= STMPE_BLOCK_GPIO; } diff --git a/drivers/of/base.c b/drivers/of/base.c index 4241e65..63ff647 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -28,6 +28,14 @@ #include #include +/* + * Iterate over all nodes of a tree. As a devicetree does not + * have a dedicated list head, the start node (usually the root + * node) will not be iterated over. + */ +#define of_tree_for_each_node(node, root) \ + list_for_each_entry(node, &root->list, list) + /** * struct alias_prop - Alias property in 'aliases' node * @link: List node to link the structure in aliases_lookup list @@ -102,16 +110,21 @@ of_bus_default_count_cells(dev, addrc, sizec); } -struct property *of_find_property(const struct device_node *node, const char *name) +struct property *of_find_property(const struct device_node *np, + const char *name, int *lenp) { - struct property *p; + struct property *pp; - if (!node) + if (!np) return NULL; - list_for_each_entry(p, &node->properties, list) - if (!strcmp(p->name, name)) - return p; + list_for_each_entry(pp, &np->properties, list) + if (of_prop_cmp(pp->name, name) == 0) { + if (lenp) + *lenp = pp->length; + return pp; + } + return NULL; } EXPORT_SYMBOL(of_find_property); @@ -135,7 +148,7 @@ * the global lookup table with the properties. It returns the * number of alias_prop found, or error code in error case. */ -static void of_alias_scan(void) +void of_alias_scan(void) { struct property *pp; struct alias_prop *app, *tmp; @@ -148,7 +161,7 @@ if (!root_node) return; - of_aliases = of_find_node_by_path(root_node, "/aliases"); + of_aliases = of_find_node_by_path("/aliases"); if (!of_aliases) return; @@ -160,12 +173,12 @@ int id, len; /* Skip those we do not want to proceed */ - if (!strcmp(pp->name, "name") || - !strcmp(pp->name, "phandle") || - !strcmp(pp->name, "linux,phandle")) + if (!of_prop_cmp(pp->name, "name") || + !of_prop_cmp(pp->name, "phandle") || + !of_prop_cmp(pp->name, "linux,phandle")) continue; - np = of_find_node_by_path(root_node, pp->value); + np = of_find_node_by_path(pp->value); if (!np) continue; @@ -187,6 +200,7 @@ of_alias_add(ap, np, id, start, len); } } +EXPORT_SYMBOL(of_alias_scan); /** * of_alias_get_id - Get alias id for the given device_node @@ -202,7 +216,7 @@ int id = -ENODEV; list_for_each_entry(app, &aliases_lookup, link) { - if (strcmp(app->stem, stem) != 0) + if (of_node_cmp(app->stem, stem) != 0) continue; if (np == app->np) { @@ -220,7 +234,7 @@ struct property *pp; list_for_each_entry(pp, &of_aliases->properties, list) { - if (!strcmp(np->full_name, pp->value)) + if (!of_node_cmp(np->full_name, pp->value)) return pp->name; } @@ -240,7 +254,7 @@ return addr; node = node->parent; - p = of_find_property(node, "ranges"); + p = of_find_property(node, "ranges", NULL); if (!p && node->parent) return OF_BAD_ADDR; of_bus_count_cells(node, &na, &nc); @@ -275,13 +289,7 @@ const void *of_get_property(const struct device_node *np, const char *name, int *lenp) { - struct property *pp = of_find_property(np, name); - - if (!pp) - return NULL; - - if (lenp) - *lenp = pp->length; + struct property *pp = of_find_property(np, name, lenp); return pp ? pp->value : NULL; } @@ -300,7 +308,7 @@ if (cp == NULL) return 0; while (cplen > 0) { - if (strcmp(cp, compat) == 0) + if (of_compat_cmp(cp, compat, strlen(compat)) == 0) return 1; l = strlen(cp) + 1; cp += l; @@ -312,6 +320,88 @@ EXPORT_SYMBOL(of_device_is_compatible); /** + * of_find_node_by_name - Find a node by its "name" property + * @from: The node to start searching from or NULL, the node + * you pass will not be searched, only the next one + * will; typically, you pass what the previous call + * returned. + * @name: The name string to match against + * + * Returns a pointer to the node found or NULL. + */ +struct device_node *of_find_node_by_name(struct device_node *from, + const char *name) +{ + struct device_node *np; + + if (!from) + from = root_node; + + of_tree_for_each_node(np, from) + if (np->name && !of_node_cmp(np->name, name)) + return np; + + return NULL; +} +EXPORT_SYMBOL(of_find_node_by_name); + +/** + * of_find_compatible_node - Find a node based on type and one of the + * tokens in its "compatible" property + * @from: The node to start searching from or NULL, the node + * you pass will not be searched, only the next one + * will; typically, you pass what the previous call + * returned. + * @type: The type string to match "device_type" or NULL to ignore + * (currently always ignored in barebox) + * @compatible: The string to match to one of the tokens in the device + * "compatible" list. + * + * Returns a pointer to the node found or NULL. + */ +struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compatible) +{ + struct device_node *np; + + if (!from) + from = root_node; + + of_tree_for_each_node(np, from) + if (of_device_is_compatible(np, compatible)) + return np; + + return NULL; +} +EXPORT_SYMBOL(of_find_compatible_node); + +/** + * of_find_node_with_property - Find a node which has a property with + * the given name. + * @from: The node to start searching from or NULL, the node + * you pass will not be searched, only the next one + * will; typically, you pass what the previous call + * returned. + * @prop_name: The name of the property to look for. + * + * Returns a pointer to the node found or NULL. + */ +struct device_node *of_find_node_with_property(struct device_node *from, + const char *prop_name) +{ + struct device_node *np; + + of_tree_for_each_node(np, from) { + struct property *pp = of_find_property(np, prop_name, NULL); + if (pp) + return np; + } + + return NULL; +} +EXPORT_SYMBOL(of_find_node_with_property); + +/** * of_match_node - Tell if an device_node has a matching of_match structure * @matches: array of of device match structures to search in * @node: the of device structure to match against @@ -321,6 +411,9 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches, const struct device_node *node) { + if (!matches || !node) + return NULL; + while (matches->compatible) { if (of_device_is_compatible(node, matches->compatible) == 1) return matches; @@ -330,6 +423,43 @@ return NULL; } +/** + * of_find_matching_node_and_match - Find a node based on an of_device_id + * match table. + * @from: The node to start searching from or NULL, the node + * you pass will not be searched, only the next one + * will; typically, you pass what the previous call + * returned. + * @matches: array of of device match structures to search in + * @match Updated to point at the matches entry which matched + * + * Returns a pointer to the node found or NULL. + */ +struct device_node *of_find_matching_node_and_match(struct device_node *from, + const struct of_device_id *matches, + const struct of_device_id **match) +{ + struct device_node *np; + + if (match) + *match = NULL; + + if (!from) + from = root_node; + + of_tree_for_each_node(np, from) { + const struct of_device_id *m = of_match_node(matches, np); + if (m) { + if (match) + *match = m; + return np; + } + } + + return NULL; +} +EXPORT_SYMBOL(of_find_matching_node_and_match); + int of_match(struct device_d *dev, struct driver_d *drv) { const struct of_device_id *id; @@ -345,12 +475,137 @@ EXPORT_SYMBOL(of_match); /** + * of_find_property_value_of_size + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @len: requested length of property value + * + * Search for a property in a device node and valid the requested size. + * Returns the property value on success, -EINVAL if the property does not + * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + */ +static void *of_find_property_value_of_size(const struct device_node *np, + const char *propname, u32 len) +{ + struct property *prop = of_find_property(np, propname, NULL); + + if (!prop) + return ERR_PTR(-EINVAL); + if (!prop->value) + return ERR_PTR(-ENODATA); + if (len > prop->length) + return ERR_PTR(-EOVERFLOW); + + return prop->value; +} + +/** + * of_property_read_u32_index - Find and read a u32 from a multi-value property. + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @index: index of the u32 in the list of values + * @out_value: pointer to return value, modified only if no error. + * + * Search for a property in a device node and read nth 32-bit value from + * it. Returns 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + * The out_value is modified only if a valid u32 value can be decoded. + */ +int of_property_read_u32_index(const struct device_node *np, + const char *propname, + u32 index, u32 *out_value) +{ + const u32 *val = of_find_property_value_of_size(np, propname, + ((index + 1) * sizeof(*out_value))); + + if (IS_ERR(val)) + return PTR_ERR(val); + + *out_value = be32_to_cpup(((__be32 *)val) + index); + return 0; +} +EXPORT_SYMBOL_GPL(of_property_read_u32_index); + +/** + * of_property_read_u8_array - Find and read an array of u8 from a property. + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @out_value: pointer to return value, modified only if return value is 0. + * @sz: number of array elements to read + * + * Search for a property in a device node and read 8-bit value(s) from + * it. Returns 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + * dts entry of array should be like: + * property = /bits/ 8 <0x50 0x60 0x70>; + * + * The out_value is modified only if a valid u8 value can be decoded. + */ +int of_property_read_u8_array(const struct device_node *np, + const char *propname, u8 *out_values, size_t sz) +{ + const u8 *val = of_find_property_value_of_size(np, propname, + (sz * sizeof(*out_values))); + + if (IS_ERR(val)) + return PTR_ERR(val); + + while (sz--) + *out_values++ = *val++; + return 0; +} +EXPORT_SYMBOL_GPL(of_property_read_u8_array); + +/** + * of_property_read_u16_array - Find and read an array of u16 from a property. + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @out_value: pointer to return value, modified only if return value is 0. + * @sz: number of array elements to read + * + * Search for a property in a device node and read 16-bit value(s) from + * it. Returns 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + * dts entry of array should be like: + * property = /bits/ 16 <0x5000 0x6000 0x7000>; + * + * The out_value is modified only if a valid u16 value can be decoded. + */ +int of_property_read_u16_array(const struct device_node *np, + const char *propname, u16 *out_values, size_t sz) +{ + const __be16 *val = of_find_property_value_of_size(np, propname, + (sz * sizeof(*out_values))); + + if (IS_ERR(val)) + return PTR_ERR(val); + + while (sz--) + *out_values++ = be16_to_cpup(val++); + return 0; +} +EXPORT_SYMBOL_GPL(of_property_read_u16_array); + +/** * of_property_read_u32_array - Find and read an array of 32 bit integers * from a property. * * @np: device node from which the property value is to be read. * @propname: name of the property to be searched. * @out_value: pointer to return value, modified only if return value is 0. + * @sz: number of array elements to read * * Search for a property in a device node and read 32-bit value(s) from * it. Returns 0 on success, -EINVAL if the property does not exist, @@ -363,222 +618,44 @@ const char *propname, u32 *out_values, size_t sz) { - struct property *prop = of_find_property(np, propname); - const __be32 *val; + const __be32 *val = of_find_property_value_of_size(np, propname, + (sz * sizeof(*out_values))); - if (!prop) - return -EINVAL; - if (!prop->value) - return -ENODATA; - if ((sz * sizeof(*out_values)) > prop->length) - return -EOVERFLOW; + if (IS_ERR(val)) + return PTR_ERR(val); - val = prop->value; while (sz--) *out_values++ = be32_to_cpup(val++); return 0; } EXPORT_SYMBOL_GPL(of_property_read_u32_array); -int of_property_write_u32_array(struct device_node *np, - const char *propname, const u32 *values, - size_t sz) +/** + * of_property_read_u64 - Find and read a 64 bit integer from a property + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @out_value: pointer to return value, modified only if return value is 0. + * + * Search for a property in a device node and read a 64-bit value from + * it. Returns 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + * The out_value is modified only if a valid u64 value can be decoded. + */ +int of_property_read_u64(const struct device_node *np, const char *propname, + u64 *out_value) { - struct property *prop = of_find_property(np, propname); - __be32 *val; + const __be32 *val = of_find_property_value_of_size(np, propname, + sizeof(*out_value)); - if (!prop) - prop = of_new_property(np, propname, NULL, 0); - if (!prop) - return -ENOMEM; + if (IS_ERR(val)) + return PTR_ERR(val); - free(prop->value); - - prop->value = malloc(sizeof(__be32) * sz); - if (!prop->value) - return -ENOMEM; - - val = prop->value; - - while (sz--) - *val++ = cpu_to_be32(*values++); + *out_value = of_read_number(val, 2); return 0; } - -/** - * of_parse_phandles_with_args - Find a node pointed by phandle in a list - * @np: pointer to a device tree node containing a list - * @list_name: property name that contains a list - * @cells_name: property name that specifies phandles' arguments count - * @index: index of a phandle to parse out - * @out_node: optional pointer to device_node struct pointer (will be filled) - * @out_args: optional pointer to arguments pointer (will be filled) - * - * This function is useful to parse lists of phandles and their arguments. - * Returns 0 on success and fills out_node and out_args, on error returns - * appropriate errno value. - * - * Example: - * - * phandle1: node1 { - * #list-cells = <2>; - * } - * - * phandle2: node2 { - * #list-cells = <1>; - * } - * - * node3 { - * list = <&phandle1 1 2 &phandle2 3>; - * } - * - * To get a device_node of the `node2' node you may call this: - * of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args); - */ -int of_parse_phandles_with_args(struct device_node *np, const char *list_name, - const char *cells_name, int index, - struct device_node **out_node, - const void **out_args) -{ - int ret = -EINVAL; - const __be32 *list; - const __be32 *list_end; - int size; - int cur_index = 0; - struct device_node *node = NULL; - const void *args = NULL; - - list = of_get_property(np, list_name, &size); - if (!list) { - ret = -ENOENT; - goto err0; - } - list_end = list + size / sizeof(*list); - - while (list < list_end) { - const __be32 *cells; - phandle phandle; - - phandle = be32_to_cpup(list++); - args = list; - - /* one cell hole in the list = <>; */ - if (!phandle) - goto next; - - node = of_find_node_by_phandle(phandle); - if (!node) { - pr_debug("%s: could not find phandle %d\n", - np->full_name, phandle); - goto err0; - } - - cells = of_get_property(node, cells_name, &size); - if (!cells || size != sizeof(*cells)) { - pr_debug("%s: could not get %s for %s\n", - np->full_name, cells_name, node->full_name); - goto err1; - } - - list += be32_to_cpup(cells); - if (list > list_end) { - pr_debug("%s: insufficient arguments length\n", - np->full_name); - goto err1; - } -next: - if (cur_index == index) - break; - - node = NULL; - args = NULL; - cur_index++; - } - - if (!node) { - /* - * args w/o node indicates that the loop above has stopped at - * the 'hole' cell. Report this differently. - */ - if (args) - ret = -EEXIST; - else - ret = -ENOENT; - goto err0; - } - - if (out_node) - *out_node = node; - if (out_args) - *out_args = args; - - return 0; -err1: -err0: - pr_debug("%s failed with status %d\n", __func__, ret); - return ret; -} -EXPORT_SYMBOL(of_parse_phandles_with_args); - -/** - * of_machine_is_compatible - Test root of device tree for a given compatible value - * @compat: compatible string to look for in root node's compatible property. - * - * Returns true if the root node has the given value in its - * compatible property. - */ -int of_machine_is_compatible(const char *compat) -{ - if (!root_node) - return 0; - - return of_device_is_compatible(root_node, compat); -} -EXPORT_SYMBOL(of_machine_is_compatible); - -/** - * of_find_node_by_path - Find a node matching a full OF path - * @root: The root node of this tree - * @path: The full path to match - * - * Returns a node pointer with refcount incremented, use - * of_node_put() on it when done. - */ -struct device_node *of_find_node_by_path(struct device_node *root, const char *path) -{ - char *slash, *p, *freep; - struct device_node *dn = root; - - if (*path != '/') - return NULL; - - path++; - - freep = p = xstrdup(path); - - while (1) { - if (!*p) - goto out; - - slash = strchr(p, '/'); - if (slash) - *slash = 0; - - dn = of_find_child_by_name(dn, p); - if (!dn) - goto out; - - if (!slash) - goto out; - - p = slash + 1; - } -out: - free(freep); - - return dn; -} -EXPORT_SYMBOL(of_find_node_by_path); +EXPORT_SYMBOL_GPL(of_property_read_u64); /** * of_property_read_string - Find and read a string from a property @@ -598,7 +675,7 @@ int of_property_read_string(struct device_node *np, const char *propname, const char **out_string) { - struct property *prop = of_find_property(np, propname); + struct property *prop = of_find_property(np, propname, NULL); if (!prop) return -EINVAL; if (!prop->value) @@ -631,7 +708,7 @@ int of_property_read_string_index(struct device_node *np, const char *propname, int index, const char **output) { - struct property *prop = of_find_property(np, propname); + struct property *prop = of_find_property(np, propname, NULL); int i = 0; size_t l = 0, total = 0; const char *p; @@ -657,6 +734,551 @@ EXPORT_SYMBOL_GPL(of_property_read_string_index); /** + * of_property_match_string() - Find string in a list and return index + * @np: pointer to node containing string list property + * @propname: string list property name + * @string: pointer to string to search for in string list + * + * This function searches a string list property and returns the index + * of a specific string value. + */ +int of_property_match_string(struct device_node *np, const char *propname, + const char *string) +{ + struct property *prop = of_find_property(np, propname, NULL); + size_t l; + int i; + const char *p, *end; + + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + + p = prop->value; + end = p + prop->length; + + for (i = 0; p < end; i++, p += l) { + l = strlen(p) + 1; + if (p + l > end) + return -EILSEQ; + pr_debug("comparing %s with %s\n", string, p); + if (strcmp(string, p) == 0) + return i; /* Found it; return index */ + } + return -ENODATA; +} +EXPORT_SYMBOL_GPL(of_property_match_string); + +/** + * of_property_count_strings - Find and return the number of strings from a + * multiple strings property. + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device tree node and retrieve the number of null + * terminated string contain in it. Returns the number of strings on + * success, -EINVAL if the property does not exist, -ENODATA if property + * does not have a value, and -EILSEQ if the string is not null-terminated + * within the length of the property data. + */ +int of_property_count_strings(struct device_node *np, const char *propname) +{ + struct property *prop = of_find_property(np, propname, NULL); + int i = 0; + size_t l = 0, total = 0; + const char *p; + + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + if (strnlen(prop->value, prop->length) >= prop->length) + return -EILSEQ; + + p = prop->value; + + for (i = 0; total < prop->length; total += l, p += l, i++) + l = strlen(p) + 1; + + return i; +} +EXPORT_SYMBOL_GPL(of_property_count_strings); + +const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur, + u32 *pu) +{ + const void *curv = cur; + + if (!prop) + return NULL; + + if (!cur) { + curv = prop->value; + goto out_val; + } + + curv += sizeof(*cur); + if (curv >= prop->value + prop->length) + return NULL; + +out_val: + *pu = be32_to_cpup(curv); + return curv; +} +EXPORT_SYMBOL_GPL(of_prop_next_u32); + +const char *of_prop_next_string(struct property *prop, const char *cur) +{ + const void *curv = cur; + + if (!prop) + return NULL; + + if (!cur) + return prop->value; + + curv += strlen(cur) + 1; + if (curv >= prop->value + prop->length) + return NULL; + + return curv; +} +EXPORT_SYMBOL_GPL(of_prop_next_string); + +/** + * of_property_write_bool - Create/Delete empty (bool) property. + * + * @np: device node from which the property is to be set. + * @propname: name of the property to be set. + * + * Search for a property in a device node and create or delete the property. + * If the property already exists and write value is false, the property is + * deleted. If write value is true and the property does not exist, it is + * created. Returns 0 on success, -ENOMEM if the property or array + * of elements cannot be created. + */ +int of_property_write_bool(struct device_node *np, const char *propname, + const bool value) +{ + struct property *prop = of_find_property(np, propname, NULL); + + if (!value) { + if (prop) + of_delete_property(prop); + return 0; + } + + if (!prop) + prop = of_new_property(np, propname, NULL, 0); + if (!prop) + return -ENOMEM; + + return 0; +} + +/** + * of_property_write_u8_array - Write an array of u8 to a property. If + * the property does not exist, it will be created and appended to the given + * device node. + * + * @np: device node to which the property value is to be written. + * @propname: name of the property to be written. + * @values: pointer to array elements to write. + * @sz: number of array elements to write. + * + * Search for a property in a device node and write 8-bit value(s) to + * it. If the property does not exist, it will be created and appended to + * the device node. Returns 0 on success, -ENOMEM if the property or array + * of elements cannot be created. + */ +int of_property_write_u8_array(struct device_node *np, + const char *propname, const u8 *values, + size_t sz) +{ + struct property *prop = of_find_property(np, propname, NULL); + u8 *val; + + if (prop) + of_delete_property(prop); + + prop = of_new_property(np, propname, NULL, sizeof(*val) * sz); + if (!prop) + return -ENOMEM; + + val = prop->value; + while (sz--) + *val++ = *values++; + + return 0; +} + +/** + * of_property_write_u16_array - Write an array of u16 to a property. If + * the property does not exist, it will be created and appended to the given + * device node. + * + * @np: device node to which the property value is to be written. + * @propname: name of the property to be written. + * @values: pointer to array elements to write. + * @sz: number of array elements to write. + * + * Search for a property in a device node and write 16-bit value(s) to + * it. If the property does not exist, it will be created and appended to + * the device node. Returns 0 on success, -ENOMEM if the property or array + * of elements cannot be created. + */ +int of_property_write_u16_array(struct device_node *np, + const char *propname, const u16 *values, + size_t sz) +{ + struct property *prop = of_find_property(np, propname, NULL); + __be16 *val; + + if (prop) + of_delete_property(prop); + + prop = of_new_property(np, propname, NULL, sizeof(*val) * sz); + if (!prop) + return -ENOMEM; + + val = prop->value; + while (sz--) + *val++ = cpu_to_be16(*values++); + + return 0; +} + +/** + * of_property_write_u32_array - Write an array of u32 to a property. If + * the property does not exist, it will be created and appended to the given + * device node. + * + * @np: device node to which the property value is to be written. + * @propname: name of the property to be written. + * @values: pointer to array elements to write. + * @sz: number of array elements to write. + * + * Search for a property in a device node and write 32-bit value(s) to + * it. If the property does not exist, it will be created and appended to + * the device node. Returns 0 on success, -ENOMEM if the property or array + * of elements cannot be created. + */ +int of_property_write_u32_array(struct device_node *np, + const char *propname, const u32 *values, + size_t sz) +{ + struct property *prop = of_find_property(np, propname, NULL); + __be32 *val; + + if (prop) + of_delete_property(prop); + + prop = of_new_property(np, propname, NULL, sizeof(*val) * sz); + if (!prop) + return -ENOMEM; + + val = prop->value; + while (sz--) + *val++ = cpu_to_be32(*values++); + + return 0; +} + +/** + * of_property_write_u64_array - Write an array of u64 to a property. If + * the property does not exist, it will be created and appended to the given + * device node. + * + * @np: device node to which the property value is to be written. + * @propname: name of the property to be written. + * @values: pointer to array elements to write. + * @sz: number of array elements to write. + * + * Search for a property in a device node and write 64-bit value(s) to + * it. If the property does not exist, it will be created and appended to + * the device node. Returns 0 on success, -ENOMEM if the property or array + * of elements cannot be created. + */ +int of_property_write_u64_array(struct device_node *np, + const char *propname, const u64 *values, + size_t sz) +{ + struct property *prop = of_find_property(np, propname, NULL); + __be32 *val; + + if (prop) + of_delete_property(prop); + + prop = of_new_property(np, propname, NULL, 2 * sizeof(*val) * sz); + if (!prop) + return -ENOMEM; + + val = prop->value; + while (sz--) { + of_write_number(val, *values++, 2); + val += 2; + } + + return 0; +} + +/** + * of_parse_phandle - Resolve a phandle property to a device_node pointer + * @np: Pointer to device node holding phandle property + * @phandle_name: Name of property holding a phandle value + * @index: For properties holding a table of phandles, this is the index into + * the table + * + * Returns the device_node pointer found or NULL. + */ +struct device_node *of_parse_phandle(const struct device_node *np, + const char *phandle_name, int index) +{ + const __be32 *phandle; + int size; + + phandle = of_get_property(np, phandle_name, &size); + if ((!phandle) || (size < sizeof(*phandle) * (index + 1))) + return NULL; + + return of_find_node_by_phandle(be32_to_cpup(phandle + index)); +} +EXPORT_SYMBOL(of_parse_phandle); + +/** + * of_parse_phandle_with_args() - Find a node pointed by phandle in a list + * @np: pointer to a device tree node containing a list + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * @index: index of a phandle to parse out + * @out_args: optional pointer to output arguments structure (will be filled) + * + * This function is useful to parse lists of phandles and their arguments. + * Returns 0 on success and fills out_args, on error returns appropriate + * errno value. + * + * Example: + * + * phandle1: node1 { + * #list-cells = <2>; + * } + * + * phandle2: node2 { + * #list-cells = <1>; + * } + * + * node3 { + * list = <&phandle1 1 2 &phandle2 3>; + * } + * + * To get a device_node of the `node2' node you may call this: + * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); + */ +static int __of_parse_phandle_with_args(const struct device_node *np, + const char *list_name, + const char *cells_name, int index, + struct of_phandle_args *out_args) +{ + const __be32 *list, *list_end; + int rc = 0, size, cur_index = 0; + uint32_t count = 0; + struct device_node *node = NULL; + phandle phandle; + + /* Retrieve the phandle list property */ + list = of_get_property(np, list_name, &size); + if (!list) + return -ENOENT; + list_end = list + size / sizeof(*list); + + /* Loop over the phandles until all the requested entry is found */ + while (list < list_end) { + rc = -EINVAL; + count = 0; + + /* + * If phandle is 0, then it is an empty entry with no + * arguments. Skip forward to the next entry. + */ + phandle = be32_to_cpup(list++); + if (phandle) { + /* + * Find the provider node and parse the #*-cells + * property to determine the argument length + */ + node = of_find_node_by_phandle(phandle); + if (!node) { + pr_err("%s: could not find phandle\n", + np->full_name); + goto err; + } + if (of_property_read_u32(node, cells_name, &count)) { + pr_err("%s: could not get %s for %s\n", + np->full_name, cells_name, + node->full_name); + goto err; + } + + /* + * Make sure that the arguments actually fit in the + * remaining property data length + */ + if (list + count > list_end) { + pr_err("%s: arguments longer than property\n", + np->full_name); + goto err; + } + } + + /* + * All of the error cases above bail out of the loop, so at + * this point, the parsing is successful. If the requested + * index matches, then fill the out_args structure and return, + * or return -ENOENT for an empty entry. + */ + rc = -ENOENT; + if (cur_index == index) { + if (!phandle) + goto err; + + if (out_args) { + int i; + if (WARN_ON(count > MAX_PHANDLE_ARGS)) + count = MAX_PHANDLE_ARGS; + out_args->np = node; + out_args->args_count = count; + for (i = 0; i < count; i++) + out_args->args[i] = + be32_to_cpup(list++); + } + + /* Found it! return success */ + return 0; + } + + node = NULL; + list += count; + cur_index++; + } + + /* + * Unlock node before returning result; will be one of: + * -ENOENT : index is for empty phandle + * -EINVAL : parsing error on data + * [1..n] : Number of phandle (count mode; when index = -1) + */ + rc = index < 0 ? cur_index : -ENOENT; + err: + return rc; +} + +int of_parse_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name, int index, + struct of_phandle_args *out_args) +{ + if (index < 0) + return -EINVAL; + return __of_parse_phandle_with_args(np, list_name, cells_name, + index, out_args); +} +EXPORT_SYMBOL(of_parse_phandle_with_args); + +/** + * of_count_phandle_with_args() - Find the number of phandles references in a property + * @np: pointer to a device tree node containing a list + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * + * Returns the number of phandle + argument tuples within a property. It + * is a typical pattern to encode a list of phandle and variable + * arguments into a single property. The number of arguments is encoded + * by a property in the phandle-target node. For example, a gpios + * property would contain a list of GPIO specifies consisting of a + * phandle and 1 or more arguments. The number of arguments are + * determined by the #gpio-cells property in the node pointed to by the + * phandle. + */ +int of_count_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name) +{ + return __of_parse_phandle_with_args(np, list_name, cells_name, + -1, NULL); +} +EXPORT_SYMBOL(of_count_phandle_with_args); + +/** + * of_machine_is_compatible - Test root of device tree for a given compatible value + * @compat: compatible string to look for in root node's compatible property. + * + * Returns true if the root node has the given value in its + * compatible property. + */ +int of_machine_is_compatible(const char *compat) +{ + if (!root_node) + return 0; + + return of_device_is_compatible(root_node, compat); +} +EXPORT_SYMBOL(of_machine_is_compatible); + +/** + * of_find_node_by_path_from - Find a node matching a full OF path + * relative to a given root node. + * @path: The full path to match + * + * Returns a pointer to the node found or NULL. + */ +struct device_node *of_find_node_by_path_from(struct device_node *from, + const char *path) +{ + char *slash, *p, *freep; + + if (!from || !path || *path != '/') + return NULL; + + path++; + + freep = p = xstrdup(path); + + while (1) { + if (!*p) + goto out; + + slash = strchr(p, '/'); + if (slash) + *slash = 0; + + from = of_get_child_by_name(from, p); + if (!from) + goto out; + + if (!slash) + goto out; + + p = slash + 1; + } +out: + free(freep); + + return from; +} +EXPORT_SYMBOL(of_find_node_by_path_from); + +/** + * of_find_node_by_path - Find a node matching a full OF path + * @path: The full path to match + * + * Returns a pointer to the node found or NULL. + */ +struct device_node *of_find_node_by_path(const char *path) +{ + return of_find_node_by_path_from(root_node, path); +} +EXPORT_SYMBOL(of_find_node_by_path); + +/** * of_modalias_node - Lookup appropriate modalias for a device node * @node: pointer to a device tree node * @modalias: Pointer to buffer that modalias value will be copied into @@ -700,17 +1322,128 @@ return 0; } -static int of_node_disabled(struct device_node *node) +/** + * of_device_is_available - check if a device is available for use + * + * @device: Node to check for availability + * + * Returns 1 if the status property is absent or set to "okay" or "ok", + * 0 otherwise + */ +int of_device_is_available(const struct device_node *device) { - struct property *p; + const char *status; + int statlen; - p = of_find_property(node, "status"); - if (p) { - if (!strcmp("disabled", p->value)) + status = of_get_property(device, "status", &statlen); + if (status == NULL) + return 1; + + if (statlen > 0) { + if (!strcmp(status, "okay") || !strcmp(status, "ok")) return 1; } + return 0; } +EXPORT_SYMBOL(of_device_is_available); + +/** + * of_get_parent - Get a node's parent if any + * @node: Node to get parent + * + * Returns a pointer to the parent node or NULL if already at root. + */ +struct device_node *of_get_parent(const struct device_node *node) +{ + return (!node) ? NULL : node->parent; +} +EXPORT_SYMBOL(of_get_parent); + +/** + * of_get_next_available_child - Find the next available child node + * @node: parent node + * @prev: previous child of the parent node, or NULL to get first + * + * This function is like of_get_next_child(), except that it + * automatically skips any disabled nodes (i.e. status = "disabled"). + */ +struct device_node *of_get_next_available_child(const struct device_node *node, + struct device_node *prev) +{ + for_each_child_of_node(node, prev) + if (of_device_is_available(prev)) + return prev; + return NULL; +} +EXPORT_SYMBOL(of_get_next_available_child); + +/** + * of_get_child_count - Count child nodes of given parent node + * @parent: parent node + * + * Returns the number of child nodes or -EINVAL on NULL parent node. + */ +int of_get_child_count(const struct device_node *parent) +{ + struct device_node *child; + int num = 0; + + if (!parent) + return -EINVAL; + + for_each_child_of_node(parent, child) + num++; + + return num; +} +EXPORT_SYMBOL(of_get_child_count); + +/** + * of_get_available_child_count - Count available child nodes of given + * parent node + * @parent: parent node + * + * Returns the number of available child nodes or -EINVAL on NULL parent + * node. + */ +int of_get_available_child_count(const struct device_node *parent) +{ + struct device_node *child; + int num = 0; + + if (!parent) + return -EINVAL; + + for_each_child_of_node(parent, child) + if (of_device_is_available(child)) + num++; + + return num; +} +EXPORT_SYMBOL(of_get_available_child_count); + +/** + * of_get_child_by_name - Find the child node by name for a given parent + * @node: parent node + * @name: child name to look for. + * + * This function looks for child node for given matching name + * + * Returns a node pointer if found or NULL. + */ +struct device_node *of_get_child_by_name(const struct device_node *node, + const char *name) +{ + struct device_node *child; + + for_each_child_of_node(node, child) + if (child->name && (of_node_cmp(child->name, name) == 0)) + return child; + + return NULL; +} +EXPORT_SYMBOL(of_get_child_by_name); void of_print_nodes(struct device_node *node, int indent) { @@ -774,14 +1507,18 @@ struct property *prop; prop = xzalloc(sizeof(*prop)); - prop->name = strdup(name); - prop->length = len; - if (len) { - prop->value = xzalloc(len); - memcpy(prop->value, data, len); + if (!prop->name) { + free(prop); + return NULL; } + prop->length = len; + prop->value = xzalloc(len); + + if (data) + memcpy(prop->value, data, len); + list_add_tail(&prop->list, &node->properties); return prop; @@ -789,6 +1526,9 @@ void of_delete_property(struct property *pp) { + if (!pp) + return; + list_del(&pp->list); free(pp->name); @@ -807,26 +1547,19 @@ int of_set_property(struct device_node *np, const char *name, const void *val, int len, int create) { - struct property *pp; + struct property *pp = of_find_property(np, name, NULL); if (!np) return -ENOENT; - pp = of_find_property(np, name); - if (pp) { - void *data; + if (!pp && !create) + return -ENOENT; - free(pp->value); - data = xzalloc(len); - memcpy(data, val, len); - pp->value = data; - pp->length = len; - } else { - if (!create) - return -ENOENT; + of_delete_property(pp); - pp = of_new_property(np, name, val, len); - } + pp = of_new_property(np, name, val, len); + if (!pp) + return -ENOMEM; return 0; } @@ -904,7 +1637,7 @@ { const struct property *cp; - if (of_node_disabled(node)) + if (!of_device_is_available(node)) return NULL; cp = of_get_property(node, "compatible", NULL); @@ -938,7 +1671,7 @@ if (ret) return -ENXIO; - if (strcmp(device_type, "memory")) + if (of_node_cmp(device_type, "memory")) return -ENXIO; of_bus_count_cells(node, &na, &nc); @@ -1050,12 +1783,8 @@ if (!node) return; - list_for_each_entry_safe(p, pt, &node->properties, list) { - list_del(&p->list); - free(p->name); - free(p->value); - free(p); - } + list_for_each_entry_safe(p, pt, &node->properties, list) + of_delete_property(p); list_for_each_entry_safe(n, nt, &node->children, parent_list) { of_free(n); @@ -1137,12 +1866,12 @@ if(!root_node) return -ENODEV; - of_chosen = of_find_node_by_path(root_node, "/chosen"); + of_chosen = of_find_node_by_path("/chosen"); of_property_read_string(root_node, "model", &of_model); __of_parse_phandles(root_node); - memory = of_find_node_by_path(root_node, "/memory"); + memory = of_find_node_by_path("/memory"); if (memory) of_add_memory(memory, false); @@ -1152,17 +1881,6 @@ return 0; } -struct device_node *of_find_child_by_name(struct device_node *node, const char *name) -{ - struct device_node *_n; - - device_node_for_nach_child(node, _n) - if (!strcmp(_n->name, name)) - return _n; - - return NULL; -} - /** * of_create_node - create a new node including its parents * @path - the nodepath to create @@ -1187,7 +1905,7 @@ if (slash) *slash = 0; - tmp = of_find_child_by_name(dn, p); + tmp = of_get_child_by_name(dn, p); if (tmp) dn = tmp; else @@ -1215,8 +1933,8 @@ name = of_get_property(of_chosen, "linux,stdout-path", NULL); if (name == NULL) return 0; - dn = of_find_node_by_path(root_node, name); + dn = of_find_node_by_path(name); if (!dn) return 0; @@ -1245,7 +1963,7 @@ struct device_node *chosen; __be32 buf[2]; - chosen = of_find_node_by_path(root, "/chosen"); + chosen = of_find_node_by_path("/chosen"); if (!chosen) return -EINVAL; @@ -1257,11 +1975,11 @@ } else { struct property *pp; - pp = of_find_property(chosen, "linux,initrd-start"); + pp = of_find_property(chosen, "linux,initrd-start", NULL); if (pp) of_delete_property(pp); - pp = of_find_property(chosen, "linux,initrd-end"); + pp = of_find_property(chosen, "linux,initrd-end", NULL); if (pp) of_delete_property(pp); } diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index a3ec576..afaa4e0 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -61,7 +61,7 @@ int len; /* length of the property */ const struct fdt_property *fdt_prop; const char *pathp, *name; - struct device_node *node = NULL, *n; + struct device_node *node = NULL; struct property *p; uint32_t dt_struct; struct fdt_node_header *fnh; @@ -135,9 +135,10 @@ if (!node) { node = root; } else { - if (merge && (n = of_find_child_by_name(node, pathp))) - node = n; - else + if (merge) + node = of_get_child_by_name(node, + pathp); + if (!merge || !node) node = of_new_node(node, pathp); } @@ -178,7 +179,10 @@ goto err; } - if (merge && (p = of_find_property(node, name))) { + p = NULL; + if (merge) + p = of_find_property(node, name, NULL); + if (merge && p) { free(p->value); p->value = xzalloc(len); memcpy(p->value, nodep, len); diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c index 83b72c0..41e91ec 100644 --- a/drivers/of/gpio.c +++ b/drivers/of/gpio.c @@ -9,17 +9,16 @@ const char *propname, int index) { int ret; - struct device_node *gpio_np; - const void *gpio_spec; + struct of_phandle_args out_args; - ret = of_parse_phandles_with_args(np, propname, "#gpio-cells", index, - &gpio_np, &gpio_spec); + ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", + index, &out_args); if (ret) { pr_debug("%s: can't parse gpios property: %d\n", __func__, ret); return -EINVAL; } - ret = gpio_get_num(gpio_np->device, be32_to_cpup(gpio_spec)); + ret = gpio_get_num(out_args.np->device, out_args.args[0]); if (ret < 0) return ret; diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c index de93fbc..2bf05e2 100644 --- a/drivers/of/of_net.c +++ b/drivers/of/of_net.c @@ -76,15 +76,15 @@ { struct property *pp; - pp = of_find_property(np, "mac-address"); + pp = of_find_property(np, "mac-address", NULL); if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value)) return pp->value; - pp = of_find_property(np, "local-mac-address"); + pp = of_find_property(np, "local-mac-address", NULL); if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value)) return pp->value; - pp = of_find_property(np, "address"); + pp = of_find_property(np, "address", NULL); if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value)) return pp->value; diff --git a/drivers/of/partition.c b/drivers/of/partition.c index 2d70cf5..e4b7d1e 100644 --- a/drivers/of/partition.c +++ b/drivers/of/partition.c @@ -29,7 +29,7 @@ const char *partname; char *filename; - device_node_for_nach_child(node, n) { + for_each_child_of_node(node, n) { const __be32 *reg; unsigned long offset, size; const char *name; diff --git a/drivers/pinctrl/pinctrl.c b/drivers/pinctrl/pinctrl.c index fa979a1..7c797d3 100644 --- a/drivers/pinctrl/pinctrl.c +++ b/drivers/pinctrl/pinctrl.c @@ -64,14 +64,14 @@ if (!np) return 0; - if (!of_find_property(np, "pinctrl-0")) + if (!of_find_property(np, "pinctrl-0", NULL)) return 0; /* For each defined state ID */ for (state = 0; ; state++) { /* Retrieve the pinctrl-* property */ propname = asprintf("pinctrl-%d", state); - prop = of_find_property(np, propname); + prop = of_find_property(np, propname, NULL); free(propname); if (!prop) { diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index f460a7a..5d4dfd6 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -107,22 +107,22 @@ struct spi_board_info chip; struct property *reg; - device_node_for_nach_child(node, n) { + for_each_child_of_node(node, n) { memset(&chip, 0, sizeof(chip)); chip.name = xstrdup(n->name); chip.bus_num = master->bus_num; /* Mode (clock phase/polarity/etc.) */ - if (of_find_property(n, "spi-cpha")) + if (of_find_property(n, "spi-cpha", NULL)) chip.mode |= SPI_CPHA; - if (of_find_property(n, "spi-cpol")) + if (of_find_property(n, "spi-cpol", NULL)) chip.mode |= SPI_CPOL; - if (of_find_property(n, "spi-cs-high")) + if (of_find_property(n, "spi-cs-high", NULL)) chip.mode |= SPI_CS_HIGH; - if (of_find_property(n, "spi-3wire")) + if (of_find_property(n, "spi-3wire", NULL)) chip.mode |= SPI_3WIRE; of_property_read_u32(n, "spi-max-frequency", &chip.max_speed_hz); - reg = of_find_property(n, "reg"); + reg = of_find_property(n, "reg", NULL); if (!reg) continue; chip.chip_select = of_read_number(reg->value, 1); diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index 80a51b7..a0dab70 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -76,16 +76,15 @@ static int imx_chipidea_probe_dt(struct imx_chipidea *ci) { - const void *out_args; - struct device_node *usbmisc_np; + struct of_phandle_args out_args; enum usb_dr_mode mode; enum usb_phy_interface phymode; - of_parse_phandles_with_args(ci->dev->device_node, "fsl,usbmisc", - "#index-cells", 0, &usbmisc_np, &out_args); + if (of_parse_phandle_with_args(ci->dev->device_node, "fsl,usbmisc", + "#index-cells", 0, &out_args)) + return -ENODEV; - ci->portno = be32_to_cpup(out_args); - + ci->portno = out_args.args[0]; ci->flags = MXC_EHCI_MODE_UTMI_8BIT; mode = of_usb_get_dr_mode(ci->dev->device_node, NULL); @@ -122,7 +121,8 @@ return -EINVAL; } - if (of_find_property(ci->dev->device_node, "disable-over-current")) + if (of_find_property(ci->dev->device_node, + "disable-over-current", NULL)) ci->flags |= MXC_EHCI_DISABLE_OVERCURRENT; return 0; diff --git a/include/linux/string.h b/include/linux/string.h index afd0aa6..658264c 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -53,6 +53,15 @@ #ifndef __HAVE_ARCH_STRNCMP extern int strncmp(const char *,const char *,__kernel_size_t); #endif +#ifndef __HAVE_ARCH_STRNICMP +extern int strnicmp(const char *, const char *, __kernel_size_t); +#endif +#ifndef __HAVE_ARCH_STRCASECMP +extern int strcasecmp(const char *s1, const char *s2); +#endif +#ifndef __HAVE_ARCH_STRNCASECMP +extern int strncasecmp(const char *s1, const char *s2, size_t n); +#endif #ifndef __HAVE_ARCH_STRCHR extern char * _strchr(const char *,int); #endif diff --git a/include/of.h b/include/of.h index 300b706..b392ca9 100644 --- a/include/of.h +++ b/include/of.h @@ -5,6 +5,11 @@ #include #include +/* Default string compare functions */ +#define of_compat_cmp(s1, s2, l) strcasecmp((s1), (s2)) +#define of_prop_cmp(s1, s2) strcmp((s1), (s2)) +#define of_node_cmp(s1, s2) strcasecmp((s1), (s2)) + #define OF_BAD_ADDR ((u64)-1) typedef u32 phandle; @@ -37,6 +42,13 @@ unsigned long data; }; +#define MAX_PHANDLE_ARGS 8 +struct of_phandle_args { + struct device_node *np; + int args_count; + uint32_t args[MAX_PHANDLE_ARGS]; +}; + #define OF_MAX_RESERVE_MAP 16 struct of_reserve_map { uint64_t start[OF_MAX_RESERVE_MAP]; @@ -59,32 +71,10 @@ int of_add_initrd(struct device_node *root, resource_size_t start, resource_size_t end); -int of_n_addr_cells(struct device_node *np); -int of_n_size_cells(struct device_node *np); - -struct property *of_find_property(const struct device_node *node, const char *name); - -struct device_node *of_find_node_by_path(struct device_node *root, const char *path); - -struct device_node *of_find_child_by_name(struct device_node *node, const char *name); - struct fdt_header *fdt_get_tree(void); struct fdt_header *of_get_fixed_tree(struct device_node *node); -int of_modalias_node(struct device_node *node, char *modalias, int len); - -#define device_node_for_nach_child(node, child) \ - list_for_each_entry(child, &node->children, parent_list) - -/* - * Iterate over all nodes of a tree. As a devicetree does not - * have a dedicated list head, the start node (usually the root - * node) will not be iterated over. - */ -#define of_tree_for_each_node(node, root) \ - list_for_each_entry(node, &root->list, list) - /* Helper to read a big number; size is in cells (not bytes) */ static inline u64 of_read_number(const __be32 *cell, int size) { @@ -105,48 +95,12 @@ } } -int of_property_read_u32_array(const struct device_node *np, - const char *propname, u32 *out_values, - size_t sz); - -static inline int of_property_read_u32(const struct device_node *np, - const char *propname, - u32 *out_value) -{ - return of_property_read_u32_array(np, propname, out_value, 1); -} - -int of_property_write_u32_array(struct device_node *np, - const char *propname, const u32 *values, - size_t sz); - -static inline int of_property_write_u32(struct device_node *np, - const char *propname, - u32 value) -{ - return of_property_write_u32_array(np, propname, &value, 1); -} - -const void *of_get_property(const struct device_node *np, const char *name, - int *lenp); - -int of_parse_phandles_with_args(struct device_node *np, const char *list_name, - const char *cells_name, int index, - struct device_node **out_node, - const void **out_args); - int of_get_named_gpio(struct device_node *np, const char *propname, int index); -struct device_node *of_find_node_by_phandle(phandle phandle); void of_print_property(const void *data, int len); void of_print_cmdline(struct device_node *root); -int of_device_is_compatible(const struct device_node *device, - const char *compat); - -int of_machine_is_compatible(const char *compat); - u64 of_translate_address(struct device_node *node, const __be32 *in_addr); #define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 @@ -155,40 +109,130 @@ void of_print_nodes(struct device_node *node, int indent); int of_probe(void); int of_parse_dtb(struct fdt_header *fdt); -void of_free(struct device_node *node); struct device_node *of_unflatten_dtb(struct device_node *root, void *fdt); -struct device_node *of_new_node(struct device_node *parent, const char *name); -struct property *of_new_property(struct device_node *node, const char *name, - const void *data, int len); -void of_delete_property(struct property *pp); - -int of_property_read_string(struct device_node *np, const char *propname, - const char **out_string); -int of_property_read_string_index(struct device_node *np, const char *propname, - int index, const char **output); -int of_set_property(struct device_node *node, const char *p, const void *val, int len, - int create); -struct device_node *of_create_node(struct device_node *root, const char *path); - -int of_set_root_node(struct device_node *); - -const struct of_device_id *of_match_node(const struct of_device_id *matches, - const struct device_node *node); struct cdev; #ifdef CONFIG_OFTREE -int of_parse_partitions(struct cdev *cdev, struct device_node *node); +extern int of_n_addr_cells(struct device_node *np); +extern int of_n_size_cells(struct device_node *np); -int of_alias_get_id(struct device_node *np, const char *stem); -const char *of_alias_get(struct device_node *np); +extern struct property *of_find_property(const struct device_node *np, + const char *name, int *lenp); +extern const void *of_get_property(const struct device_node *np, + const char *name, int *lenp); + +extern int of_set_property(struct device_node *node, const char *p, + const void *val, int len, int create); +extern struct property *of_new_property(struct device_node *node, + const char *name, const void *data, int len); +extern void of_delete_property(struct property *pp); + +extern struct device_node *of_find_node_by_name(struct device_node *from, + const char *name); +extern struct device_node *of_find_node_by_path_from(struct device_node *from, + const char *path); +extern struct device_node *of_find_node_by_path(const char *path); +extern struct device_node *of_find_node_by_phandle(phandle phandle); +extern struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compat); +extern const struct of_device_id *of_match_node( + const struct of_device_id *matches, const struct device_node *node); +extern struct device_node *of_find_matching_node_and_match( + struct device_node *from, + const struct of_device_id *matches, + const struct of_device_id **match); +extern struct device_node *of_find_node_with_property( + struct device_node *from, const char *prop_name); + +extern struct device_node *of_new_node(struct device_node *parent, + const char *name); +extern struct device_node *of_create_node(struct device_node *root, + const char *path); +extern void of_free(struct device_node *node); + +extern int of_machine_is_compatible(const char *compat); +extern int of_device_is_compatible(const struct device_node *device, + const char *compat); +extern int of_device_is_available(const struct device_node *device); + +extern struct device_node *of_get_parent(const struct device_node *node); +extern struct device_node *of_get_next_available_child( + const struct device_node *node, struct device_node *prev); +extern int of_get_child_count(const struct device_node *parent); +extern int of_get_available_child_count(const struct device_node *parent); +extern struct device_node *of_get_child_by_name(const struct device_node *node, + const char *name); + +extern int of_property_read_u32_index(const struct device_node *np, + const char *propname, + u32 index, u32 *out_value); +extern int of_property_read_u8_array(const struct device_node *np, + const char *propname, u8 *out_values, size_t sz); +extern int of_property_read_u16_array(const struct device_node *np, + const char *propname, u16 *out_values, size_t sz); +extern int of_property_read_u32_array(const struct device_node *np, + const char *propname, + u32 *out_values, + size_t sz); +extern int of_property_read_u64(const struct device_node *np, + const char *propname, u64 *out_value); + +extern int of_property_read_string(struct device_node *np, + const char *propname, + const char **out_string); +extern int of_property_read_string_index(struct device_node *np, + const char *propname, + int index, const char **output); +extern int of_property_match_string(struct device_node *np, + const char *propname, + const char *string); +extern int of_property_count_strings(struct device_node *np, + const char *propname); + +extern const __be32 *of_prop_next_u32(struct property *prop, + const __be32 *cur, u32 *pu); +extern const char *of_prop_next_string(struct property *prop, const char *cur); + +extern int of_property_write_bool(struct device_node *np, + const char *propname, const bool value); +extern int of_property_write_u8_array(struct device_node *np, + const char *propname, const u8 *values, + size_t sz); +extern int of_property_write_u16_array(struct device_node *np, + const char *propname, const u16 *values, + size_t sz); +extern int of_property_write_u32_array(struct device_node *np, + const char *propname, const u32 *values, + size_t sz); +extern int of_property_write_u64_array(struct device_node *np, + const char *propname, const u64 *values, + size_t sz); + +extern struct device_node *of_parse_phandle(const struct device_node *np, + const char *phandle_name, + int index); +extern int of_parse_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name, int index, + struct of_phandle_args *out_args); +extern int of_count_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name); + +extern void of_alias_scan(void); +extern int of_alias_get_id(struct device_node *np, const char *stem); +extern const char *of_alias_get(struct device_node *np); +extern int of_modalias_node(struct device_node *node, char *modalias, int len); + +extern struct device_node *of_get_root_node(void); +extern int of_set_root_node(struct device_node *node); + +int of_parse_partitions(struct cdev *cdev, struct device_node *node); int of_device_is_stdout_path(struct device_d *dev); const char *of_get_model(void); void *of_flatten_dtb(struct device_node *node); int of_add_memory(struct device_node *node, bool dump); void of_add_memory_bank(struct device_node *node, bool dump, int r, u64 base, u64 size); -struct device_node *of_get_root_node(void); #else static inline int of_parse_partitions(struct cdev *cdev, struct device_node *node) @@ -196,16 +240,6 @@ return -EINVAL; } -static inline int of_alias_get_id(struct device_node *np, const char *stem) -{ - return -ENOENT; -} - -static inline const char *of_alias_get(struct device_node *np) -{ - return NULL; -} - static inline int of_device_is_stdout_path(struct device_d *dev) { return 0; @@ -230,6 +264,412 @@ { return NULL; } + +static inline int of_set_root_node(struct device_node *node) +{ + return -ENOSYS; +} + +static inline int of_n_addr_cells(struct device_node *np) +{ + return 0; +} + +static inline int of_n_size_cells(struct device_node *np) +{ + return 0; +} + +static inline struct device_node *of_get_parent(const struct device_node *node) +{ + return NULL; +} + +static inline struct device_node *of_get_next_available_child( + const struct device_node *node, struct device_node *prev) +{ + return NULL; +} + +static inline int of_get_child_count(const struct device_node *parent) +{ + return -ENOSYS; +} + +static inline int of_get_available_child_count(const struct device_node *parent) +{ + return -ENOSYS; +} + +static inline struct device_node *of_get_child_by_name( + const struct device_node *node, const char *name) +{ + return NULL; +} + +static inline struct property *of_find_property(const struct device_node *np, + const char *name, + int *lenp) +{ + return NULL; +} + +static inline const void *of_get_property(const struct device_node *np, + const char *name, int *lenp) +{ + return NULL; +} + +static inline int of_set_property(struct device_node *node, const char *p, + const void *val, int len, int create) +{ + return -ENOSYS; +} + +static inline struct property *of_new_property(struct device_node *node, + const char *name, const void *data, int len) +{ + return NULL; +} + +static inline void of_delete_property(struct property *pp) +{ +} + +static inline int of_property_read_u32_index(const struct device_node *np, + const char *propname, u32 index, u32 *out_value) +{ + return -ENOSYS; +} + +static inline int of_property_read_u8_array(const struct device_node *np, + const char *propname, u8 *out_values, size_t sz) +{ + return -ENOSYS; +} + +static inline int of_property_read_u16_array(const struct device_node *np, + const char *propname, u16 *out_values, size_t sz) +{ + return -ENOSYS; +} + +static inline int of_property_read_u32_array(const struct device_node *np, + const char *propname, u32 *out_values, size_t sz) +{ + return -ENOSYS; +} + +static inline int of_property_read_u64(const struct device_node *np, + const char *propname, u64 *out_value) +{ + return -ENOSYS; +} + +static inline int of_property_read_string(struct device_node *np, + const char *propname, const char **out_string) +{ + return -ENOSYS; +} + +static inline int of_property_read_string_index(struct device_node *np, + const char *propname, int index, const char **output) +{ + return -ENOSYS; +} + +static inline int of_property_match_string(struct device_node *np, + const char *propname, const char *string) +{ + return -ENOSYS; +} + +static inline int of_property_count_strings(struct device_node *np, + const char *propname) +{ + return -ENOSYS; +} + +static inline const __be32 *of_prop_next_u32(struct property *prop, + const __be32 *cur, u32 *pu) +{ + return 0; +} + +static inline const char *of_prop_next_string(struct property *prop, + const char *cur) +{ + return NULL; +} + +static inline int of_property_write_bool(struct device_node *np, + const char *propname, const bool value) +{ + return -ENOSYS; +} + +static inline int of_property_write_u8_array(struct device_node *np, + const char *propname, const u8 *values, size_t sz) +{ + return -ENOSYS; +} + +static inline int of_property_write_u16_array(struct device_node *np, + const char *propname, const u16 *values, size_t sz) +{ + return -ENOSYS; +} + +static inline int of_property_write_u32_array(struct device_node *np, + const char *propname, const u32 *values, size_t sz) +{ + return -ENOSYS; +} + +static inline int of_property_write_u64_array(struct device_node *np, + const char *propname, const u64 *values, size_t sz) +{ + return -ENOSYS; +} + +static inline struct device_node *of_parse_phandle(const struct device_node *np, + const char *phandle_name, int index) +{ + return NULL; +} + +static inline int of_parse_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name, int index, + struct of_phandle_args *out_args) +{ + return -ENOSYS; +} + +static inline int of_count_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name) +{ + return -ENOSYS; +} + +static inline struct device_node *of_find_node_by_path_from( + struct device_node *from, const char *path) +{ + return NULL; +} + +static inline struct device_node *of_find_node_by_path(const char *path) +{ + return NULL; +} + +static inline struct device_node *of_find_node_by_name(struct device_node *from, + const char *name) +{ + return NULL; +} + +static inline struct device_node *of_find_node_by_phandle(phandle phandle) +{ + return NULL; +} + +static inline struct device_node *of_find_compatible_node( + struct device_node *from, + const char *type, + const char *compat) +{ + return NULL; +} + +static inline const struct of_device_id *of_match_node( + const struct of_device_id *matches, const struct device_node *node) +{ + return NULL; +} + +static inline struct device_node *of_find_matching_node_and_match( + struct device_node *from, + const struct of_device_id *matches, + const struct of_device_id **match) +{ + return NULL; +} + +static inline struct device_node *of_find_node_with_property( + struct device_node *from, const char *prop_name) +{ + return NULL; +} + +static inline struct device_node *of_new_node(struct device_node *parent, + const char *name) +{ + return NULL; +} + +static inline struct device_node *of_create_node(struct device_node *root, + const char *path) +{ + return NULL; +} + +static inline void of_free(struct device_node *node) +{ +} + +static inline int of_machine_is_compatible(const char *compat) +{ + return 0; +} + +static inline int of_device_is_compatible(const struct device_node *device, + const char *compat) +{ + return 0; +} + +static inline int of_device_is_available(const struct device_node *device) +{ + return 0; +} + +static inline void of_alias_scan(void) +{ +} + +static inline int of_alias_get_id(struct device_node *np, const char *stem) +{ + return -ENOSYS; +} + +static inline const char *of_alias_get(struct device_node *np) +{ + return NULL; +} + +static inline int of_modalias_node(struct device_node *node, char *modalias, + int len) +{ + return -ENOSYS; +} #endif +#define for_each_node_by_name(dn, name) \ + for (dn = of_find_node_by_name(NULL, name); dn; \ + dn = of_find_node_by_name(dn, name)) +#define for_each_compatible_node(dn, type, compatible) \ + for (dn = of_find_compatible_node(NULL, type, compatible); dn; \ + dn = of_find_compatible_node(dn, type, compatible)) +static inline struct device_node *of_find_matching_node( + struct device_node *from, + const struct of_device_id *matches) +{ + return of_find_matching_node_and_match(from, matches, NULL); +} +#define for_each_matching_node(dn, matches) \ + for (dn = of_find_matching_node(NULL, matches); dn; \ + dn = of_find_matching_node(dn, matches)) +#define for_each_matching_node_and_match(dn, matches, match) \ + for (dn = of_find_matching_node_and_match(NULL, matches, match); \ + dn; dn = of_find_matching_node_and_match(dn, matches, match)) +#define for_each_node_with_property(dn, prop_name) \ + for (dn = of_find_node_with_property(NULL, prop_name); dn; \ + dn = of_find_node_with_property(dn, prop_name)) + +#define for_each_child_of_node(parent, child) \ + list_for_each_entry(child, &parent->children, parent_list) +#define for_each_available_child_of_node(parent, child) \ + for (child = of_get_next_available_child(parent, NULL); child != NULL; \ + child = of_get_next_available_child(parent, child)) + +/** + * of_property_read_bool - Findfrom a property + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device node. + * Returns true if the property exist false otherwise. + */ +static inline bool of_property_read_bool(const struct device_node *np, + const char *propname) +{ + struct property *prop = of_find_property(np, propname, NULL); + + return prop ? true : false; +} + +static inline int of_property_read_u8(const struct device_node *np, + const char *propname, + u8 *out_value) +{ + return of_property_read_u8_array(np, propname, out_value, 1); +} + +static inline int of_property_read_u16(const struct device_node *np, + const char *propname, + u16 *out_value) +{ + return of_property_read_u16_array(np, propname, out_value, 1); +} + +static inline int of_property_read_u32(const struct device_node *np, + const char *propname, + u32 *out_value) +{ + return of_property_read_u32_array(np, propname, out_value, 1); +} + +/* + * struct property *prop; + * const __be32 *p; + * u32 u; + * + * of_property_for_each_u32(np, "propname", prop, p, u) + * printk("U32 value: %x\n", u); + */ +#define of_property_for_each_u32(np, propname, prop, p, u) \ + for (prop = of_find_property(np, propname, NULL), \ + p = of_prop_next_u32(prop, NULL, &u); \ + p; \ + p = of_prop_next_u32(prop, p, &u)) + +/* + * struct property *prop; + * const char *s; + * + * of_property_for_each_string(np, "propname", prop, s) + * printk("String value: %s\n", s); + */ +#define of_property_for_each_string(np, propname, prop, s) \ + for (prop = of_find_property(np, propname, NULL), \ + s = of_prop_next_string(prop, NULL); \ + s; \ + s = of_prop_next_string(prop, s)) + +static inline int of_property_write_u8(struct device_node *np, + const char *propname, u8 value) +{ + return of_property_write_u8_array(np, propname, &value, 1); +} + +static inline int of_property_write_u16(struct device_node *np, + const char *propname, u16 value) +{ + return of_property_write_u16_array(np, propname, &value, 1); +} + +static inline int of_property_write_u32(struct device_node *np, + const char *propname, + u32 value) +{ + return of_property_write_u32_array(np, propname, &value, 1); +} + +static inline int of_property_write_u64(struct device_node *np, + const char *propname, + u64 value) +{ + return of_property_write_u64_array(np, propname, &value, 1); +} + #endif /* __OF_H */ diff --git a/lib/string.c b/lib/string.c index db4f2ae..f544b23 100644 --- a/lib/string.c +++ b/lib/string.c @@ -22,6 +22,66 @@ char * ___strtok; +#ifndef __HAVE_ARCH_STRNICMP +/** + * strnicmp - Case insensitive, length-limited string comparison + * @s1: One string + * @s2: The other string + * @len: the maximum number of characters to compare + */ +int strnicmp(const char *s1, const char *s2, size_t len) +{ + /* Yes, Virginia, it had better be unsigned */ + unsigned char c1, c2; + + if (!len) + return 0; + + do { + c1 = *s1++; + c2 = *s2++; + if (!c1 || !c2) + break; + if (c1 == c2) + continue; + c1 = tolower(c1); + c2 = tolower(c2); + if (c1 != c2) + break; + } while (--len); + return (int)c1 - (int)c2; +} +EXPORT_SYMBOL(strnicmp); +#endif + +#ifndef __HAVE_ARCH_STRCASECMP +int strcasecmp(const char *s1, const char *s2) +{ + int c1, c2; + + do { + c1 = tolower(*s1++); + c2 = tolower(*s2++); + } while (c1 == c2 && c1 != 0); + return c1 - c2; +} +EXPORT_SYMBOL(strcasecmp); +#endif + +#ifndef __HAVE_ARCH_STRNCASECMP +int strncasecmp(const char *s1, const char *s2, size_t n) +{ + int c1, c2; + + do { + c1 = tolower(*s1++); + c2 = tolower(*s2++); + } while ((--n > 0) && c1 == c2 && c1 != 0); + return c1 - c2; +} +EXPORT_SYMBOL(strncasecmp); +#endif + #ifndef __HAVE_ARCH_STRCPY /** * strcpy - Copy a %NUL terminated string diff --git a/net/eth.c b/net/eth.c index 7240b4d..09b3bd5 100644 --- a/net/eth.c +++ b/net/eth.c @@ -296,7 +296,7 @@ continue; } - node = of_find_node_by_path(root, edev->nodepath); + node = of_find_node_by_path(edev->nodepath); if (!node) { dev_dbg(&edev->dev, "%s: fixup node %s not found\n", __func__, edev->nodepath);